近期学习数据结构顺序表,做练习leetcode题目汇总。
26. 删除有序数组中的重复项https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/
26与27类似 用到双指针,直接画图理解 。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int i=0,j=1;
int len=nums.size();
if (len == 0)
return 0;
while(j<len)
{
if(nums[i]!=nums[j])
{
i++;
nums[i] = nums[j];
}
j++;
}
//此时i为index的下标 所以要return的话要+1
i++;
return i;
}
};
27. 移除元素https://leetcode-cn.com/problems/remove-element/
双指针yyds
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int i=0,j=0;
int len = nums.size();
while(j<len)
{
if(nums[j]!=val)
nums[i++]=nums[j++];
else
j++;
}
return i;
}
};
989. 数组形式的整数加法https://leetcode-cn.com/problems/add-to-array-form-of-integer/
对于非负整数 X 而言,X 的数组形式是每位数字按从左到右的顺序形成的数组。例如,如果 X = 1231,那么其数组形式为 [1,2,3,1]。
给定非负整数 X 的数组形式 A,返回整数 X+K 的数组形式。
示例 1:
输入:A = [1,2,0,0], K = 34
输出:[1,2,3,4]
解释:1200 + 34 = 1234
示例 2:
输入:A = [2,7,4], K = 181
输出:[4,5,5]
解释:274 + 181 = 455
示例 3:
输入:A = [2,1,5], K = 806
输出:[1,0,2,1]
解释:215 + 806 = 1021
示例 4:
输入:A = [9,9,9,9,9,9,9,9,9,9], K = 1
输出:[1,0,0,0,0,0,0,0,0,0,0]
解释:9999999999 + 1 = 10000000000
分析:这道题目看似简单,但是要把所有的情况分析完整还有很多细节处理完毕是非常不容易的,所以还是要一步一步来。
第一步根据题意,数组A要和整型的数字K相加。k的位数需要自己求出来,咱们利用一个while循环求出k的位数。(int ktemp=k;这一句我在第一次写的时候没有注意这个问题 后来在运行的时候发现这里没有这个语句会出错!
//求k的位数
int ktemp=k;
while(ktemp)
{
++kSize;
ktemp/=10;
}
然后再考虑需要把K的个、十、百等位先分离出来再与数组相加。于是在一个循环体中实现 k = k%10;k = k/10;
第二步从数组A中提取数字,已知数组A的长度为num.size(),在循环中可用到的范围是int i = num.size()-1。在A与K进行相加的时候,还需要考虑就是A、K中谁长就以谁为基准相加。所以判断 int len = numsize>kSize?numsize:kSize
第三步,我们的while循环开始了~以最长的位数为基准 依次减减,直到为0为止。以ret接收每位数相加的结果int ret = a + k%10 + nextNumber;(稍后解释a和nextNumber是怎么回事)在计算过程中总会有进位的情况 所以我们分析当ret>9的时候,需要向前进位,所以这里就需要一个判断语句。if(ret>9) => ret = ret-10;nextNumber = 1;当然 nextNumber原本是置于0的,如果这个判断成立的时候 才会变成1,然后带到下一次循环中。
在最后提交答案的时候,我发现我漏了一种情况就是,数组A的位数是小于K的时候,num[i]在每次循环中都会执行 i--,到最后它就已经超了。为了避免这种情况,我们在最一开始就设置一个条件判断i是否满足>0,如果满足则a=num[i],不满足则a=0,所以a就是这么来的。
输出的时候,想起来还需要置换一下顺序,就ok了~
下面是代码,可以参考一下:
class Solution {
public:
vector<int> addToArrayForm(vector<int>& num, int k) {
int numsize = num.size();
int kSize = 0;
//求k的位数
int ktemp=k;
while(ktemp)
{
++kSize;
ktemp/=10;
}
int len = numsize>kSize ? numsize:kSize;
int i = numsize-1;
vector<int> retA;
int nextNumber = 0; //进位
while(len--)
{
int a =0;
if(i>=0)
{
a = num[i];
i--;
}
int ret = a + k%10 + nextNumber;
k = k/10;
if(ret > 9)
{
ret=ret-10;
nextNumber = 1;
}
else nextNumber = 0;
retA.push_back(ret);
}
if(nextNumber==1)
retA.push_back(1);
int left = 0,right=retA.size()-1;
while(left<right)
{
int temp = retA[right];
retA[right] = retA[left];
retA[left] = temp;
++left;
--right;
}
return retA;
}
};
88. 合并两个有序数组https://leetcode-cn.com/problems/merge-sorted-array/
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
这是我最初第一次写的代码
int i1=0,i2=0,i=0;
vector<int> temp;
while(i1<m && i2<n)
{
if(nums1[i1]>nums2[i2]) temp.push_back(nums2[i2++]);
else temp.push_back(nums1[i1++]);
}
while(i1<m)
temp.push_back(nums1[i1++]);
while(i2<n)
temp.push_back(nums2[i2++]);
nums1 = temp;
后来想了一下,我干嘛还要新建一个temp
所以这是第二次改良版
//如果直接在nums1中做改变呢!?因为nums1的初始条件就是m+n 不用白不用
if(m==0)
nums1=nums2;
int k = nums1.size()-1;
m--;n--;
while(m>=0 && n>=0)
{
if(nums1[m]>=nums2[n])
nums1[k--]=nums1[m--];
else
nums1[k--] = nums2[n--];
}
while(n>=0)
nums1[k--] = nums2[n--];
看了看别的大佬的 学习一下。代码简单明了多了,自己做了一下批注。
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = nums1.size() - 1;
m--;
n--;
while (n >= 0) {
//最后的条件就是要把nums2中的数字排序整合到nums1中
while (m >= 0 && nums1[m] > nums2[n]) {
//当nums1中的数字比nums2的大时 直接往后移动
swap(nums1[i--], nums1[m--]);
}
swap(nums1[i--], nums2[n--]);
}
}
};
189. 旋转数组https://leetcode-cn.com/problems/rotate-array/
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1 步: [7,1,2,3,4,5,6]
向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]
这道题目非常非常好玩 它有☝️非常简单的方法,想到才是真的🐂🐸。
我来解释一下:
看示例,当K=3的时候是从后面开始,取数组后三个数字一次放在前面。这歌方法很巧妙在直接将数组分成两部分,第一部分就是前面不需要移动的数组,第二部分就是需要移到前面的数组。我们先通过一个函数,把这两个部分都置换一下就变成了[4,3,2,1,7,6,5],最后再整体置换一次[5,6,7,1,2,3,4],是不是💁magic~ 所以为了方便不写三次,我们就直接写个函数调用就可以了。
代码如下:
class Solution {
public:
void reverse(int left,int right,vector<int> &nums)
{
while(left<right)
{
int temp = nums[right];
nums[right] = nums[left];
nums[left] = temp;
right--;
left++;
}
}
void rotate(vector<int>& nums, int k) {
int size = nums.size();
k%=size;
//特别要注意这里输入的index 别搞错了
reverse(0,size-k-1,nums);
reverse(size-k,size-1,nums);
reverse(0,size-1,nums);
}
};
噢~ 链表也要学完了,我赶紧滚去刷题了😩