【优选算法必刷100题】第001~002题(双指针算法):移动零、复写零问题求解

【优选算法必刷100题】第001~002题(双指针算法):移动零、复写零问题求解

🔥个人主页:艾莉丝努力练剑

❄专栏传送门:《C语言》《数据结构与算法》C语言刷题12天IO强训LeetCode代码强化刷题洛谷刷题C/C++基础知识知识强化补充C/C++干货分享&学习过程记录测试开发要点全知道Linux操作系统编程详解笔试/面试常见算法:从基础到进阶

🍉学习方向:C/C++方向学习者

⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,为万世开太平



目录

001  移动零

1.1  思路

1.2  算法原理

1.3  代码实现  

1.4  过程推算

002  复写零

2.1  思路

2.2  算法原理

2.3  代码实现  

2.4  过程推算

结尾


001  移动零

力扣链接:283. 移动零

力扣题解链接:双指针求解【移动零】问题

题目描述:

1.1  思路

双指针算法——

创建两个数组,cur和dest——

cur:从左往右扫描数组,遍历数组

dest:已处理的区间内,非零元素的最后一个位置

cur往后遍历数组的过程中:

1、遇到0元素:cur++;

2、遇到非零元素:swap(nums[dest+1],nums[cur]),然后dest++,cur++。

也就是说——

算法思路:

在本题中,我们可以用一个cur指针来扫描整个数组,另一个dest指针用来记录非零数序列的最后一个位置。根据cur在扫描过程中遇到的不同的情况,分类处理,实现数组的划分。

在cur遍历期间,使得[0 , dest]的元素全部都是非零元素,[dest + 1 , cur - 1]的元素都是零。

1.2  算法流程

1.2.1 

初始化cur = 0(用来遍历数组),dest = -1(指向非零元素序列的最后一个位置。因为刚开始我们也不知道最后一个非零元素到底在什么位置,因此初始化为-1)

1.2.2

cur依次往后遍历每个元素,遍历到的元素会有下面两种情况:

1、遇到的元素都是0,cur直接++。因为我们的目标是让[dest + 1 , cur - 1]内的元素全都是零,因此当cur遇到0的时候,直接++,就可以让0在cur - 1的位置上,从而在[dest + 1 , cur - 1]内;

2、遇到的元素不是0,dest++,并且交换cur位置和dest位置的元素(swap),之后让cur++,扫描下一个元素。

(1)因为dest指向的位置是非零元素区间的最后一个位置,如果扫描到一个新的非零元素,那么它的位置就应该在dest + 1的位置上,因此dest先自增1;

(2)dest++之后,指向的元素就是0元素(因为非零元素区间末尾的后一个元素就是0),因此可以交换到cur所处的位置上,实现[0 , dest]的元素全部都是非零元素,[dest + 1 , cur - 1]的元素都是零。

1.3  代码实现  

代码演示:

class Solution { public: void moveZeroes(vector<int>& nums) { for(int dest = -1,cur = 0;cur < nums.size();cur++) { if(nums[cur]) swap(nums[++dest],nums[cur]); } } };
时间复杂度:O(N),空间复杂度:O(1)。

1.4  过程推算

本题整个的思路、算法原理、解题过程博主在纸上推导了一遍,大家可以参考一下!


002  复写零

力扣链接:1089. 复写零

力扣题解链接:双指针算法解决【复写零】问题

题目描述:

2.1  思路

双指针算法——

先根据“异地”操作,然后优化成双指针下的“就地”操作。

1、先找到最后一个“复写”的数: 双指针算法——

(1)先判断cur位置的值;

(2)决定dest向后走一步还是两步;

(3)判断一下dest是否已经到结束位置;

(4)cur++。

2、处理一下边界情况——

到达n-1位置,cur--,dest -= 2,复写两次0。

3、“从后往前”完成复写操作。

也就是说——

如果“从前向后”进行原地复写操作的话,由于0的出现会复写两次,导致没有复写的数会被覆盖掉。因此我们选择“从后往前”的复写策略。

但是我们选择“从后往前”的复写的时候,需要找到“最后一个复写的数”,因此我们的大体流程分两步:(1)先找到最后一个复写的数;(2)然后从后往前进行复写操作。

2.2  算法流程

2.2.1

初始化两个指针cur = 0,dest = 0;

2.2.2

找到最后一个复写的数:

1、当cur < n的时候,一直执行下面循环:

(1)判断cur位置的元素:

1)如果是0的话,dest就往后移动两位;

2)否则,dest往后移动一位。

2.2.3

判断dest是否越界到n的位置:

1、如果越界,执行以下三步:

(1)n - 1位置的值修改成0;

(2)cur向前移动一步;

(3)dest向前移动两步。

2.2.4

从cur位置开始往前遍历原数组,依次还原出复写后的结果数组:

1、判断cur位置的值:

(1)如果是0:dest以及dest - 1位置修改成0,dest -= 2;

(2)如果非零:dest位置修改成0,dest -= 1;

2、cur--,复写下一个位置。

2.3  代码实现  

代码演示:

class Solution { public: void duplicateZeros(vector<int>& arr) { //1、先找到最后一个数 int cur = 0,dest = -1,n = arr.size(); while(cur < n) { if(arr[cur]) { dest++; } else { dest += 2; } if(dest >= n - 1) break; cur++; } //2、处理边界问题 if(dest == n) { arr[n -1] = 0; cur--; dest -= 2; } //3、从后往前完成复写操作 while(cur >= 0) { if(arr[cur]) arr[dest--] = arr[cur--]; else { arr[dest--] = 0; arr[dest--] = 0; cur--; } } } };
时间复杂度:O(N),空间复杂度:O(1)。

2.4  过程推算

本题整个的思路、算法原理、解题过程博主在纸上推导了一遍,大家可以参考一下!


结尾

结语:本文内容到这里就结束了,大家不要忘记给博主“一键四连”哦!

Read more

Java字符串算法核心攻略

Java字符串算法核心攻略

Java字符串算法核心攻略 提示:在 ASCII 码(美国信息交换标准代码)中,大小写英文字母和数字的十进制数值范围如下: * 大写字母 (A - Z):65 到 90 * ‘A’ 是 65 * ‘Z’ 是 90 * 小写字母 (a - z):97 到 122 * ‘a’ 是 97 * ‘z’ 是 122 * 数字是 (0-9):48 到 57 * ‘0’ 是 48 * ‘9’ 是 57 一、必会的字符串方法 刷题前先把这些方法练熟,后面会反复用到。 1.

By Ne0inhk
【动态规划】买卖股票相关问题

【动态规划】买卖股票相关问题

一、买卖股票的最佳时机含手续费 714. 买卖股票的最佳时机含手续费 题目描述: 题目分析: 1、状态分析 其实一共就只有两种状态,不是处于 持有 状态,就是处于 未持有 状态。 * f[i]表示第i天结束后,处于 持有 状态时,最大的利润 * g[i]表示第i天结束后,处于 未持有 状态时,最大的利润 2、状态转移方程 对于f[i],有两种情况可以到达这种状态: * 在第 i-1 天时就已处于 持有 状态,然后第 i 天啥也不干,仍然保持 持有 状态。此时的最大利润就为 f[i - 1]

By Ne0inhk
从冒泡到模拟q sort函数——初见排序算法的探索和思考

从冒泡到模拟q sort函数——初见排序算法的探索和思考

国庆中秋喜相连,万家团圆乐同庆。 各位小伙伴们大家好,我是此方,在此,先祝大家双节快乐! 我们都知道排序有很多种:例如冒泡排序,插入排序,快速排序,等等很多种。 而冒泡排序,是各种计算机语言中最经典的一种排序算法。 今天我将从冒泡排序开始,到实现qsort函数的模拟。逐层深入,探索排序问题。 并给出鄙人的一些拙见。 上正文: 一,冒泡排序:最经典的排序算法 假如有一个十元素整型数组,他是完全倒着排序的:就像这样 now,我们要按照从小到大的顺序将这十个数字重新排列。 如果我们想要用冒泡排序:那么他的逻辑应该是这样的: 首先让最左边的数字和他右边的数字比较:9>8,将9和8互换位置: 让9继续和他右边的数字比较,再互换位 以此类推:9不断的比较——>移动——>再比较:最后;会到达最右边,这样,我们就让最大的数字9放在了最低位置 然后是8,接下来是7,6,5.

By Ne0inhk
算法思想之深度优先搜索(DFS)、递归以及案例(最多能得到多少克黄金、精准核酸检测、最富裕的小家庭)

算法思想之深度优先搜索(DFS)、递归以及案例(最多能得到多少克黄金、精准核酸检测、最富裕的小家庭)

深度优先搜索(DFS)、递归 * 深度优先搜索(Depth First Search,DFS)是一种用于遍历或搜索树或图的算法。在 DFS 算法中,从起始节点开始,沿着一条路径尽可能深地访问节点,直到到达叶子节点或者无法继续前进为止。然后退回到最近的一个有未探索节点的分支节点,继续探索其他路径,直到所有节点都被访问过为止。 * 深度优先搜索常常用于解决以下类型的问题:深度优先搜索是一种简单而强大的算法,可以解决许多实际问题。 * 图遍历:在无向图或有向图中寻找特定节点之间的路径、判断图的连通性等。 * 连通性问题:判断图中是否存在环、判断图的强连通分量等。 * 组合问题:生成排列、组合或子集等组合型问题。 * 寻路问题:求解从起始点到目标点的最短路径或所有可行路径。 * 递归问题:通过递归实现深度优先搜索,例如二叉树的遍历等。 小华最多能得到多少克黄金 * 题目描述小华按照地图去寻宝,地图上被划分成 m 行和 n 列的方格,横纵坐标范围分别是 [0, n-1] 和 [0, m-1]。在横坐标和纵坐标的数位之和不大于 k

By Ne0inhk