刷题入门题目总结一下
27 移除链表元素
解法一
指向同一个向量/数组的两个指针,一个表示结果的数组尾巴:p,另一个循环遍历整个数组:q。在这个过程种,如果q遇到了不合适的值就直接跳过,如果遇到了合适的值,就把他添加到p的后面。
注意特殊的情况,数组为空或者1等;
双指针法进行了许多复制操作。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
if(nums.size()==0)return nums.size();
int a=0;
for(int j=0;j<nums.size();j++){
if(nums[j]!=val)nums[a++]=nums[j];
}
return a;
}
};
解法二
为了减少不必要的复制,也就是说如果这个值不是要剔除的,就不动他,所以把重复的值删掉就可以。或者移到最后面,数组大小减一。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
for(int j=0;j<nums.size();){
if(nums[j]==val)nums.erase(nums.begin()+j);
else j++;
}
return nums.size();
}
};
35 搜索插入的位置
题目:给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。你可以假设数组中无重复元素。
方法一:
用find函数来查找,如果找到了返回索引,找不到就插入;插入后,进行排序,然后再查找、返回索引。
这种方法非常朴素,时间和空间效率都很低。
#include<algorithm>
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
vector<int>::iterator it;
it=find(nums.begin(),nums.end(),target);
if(it!=nums.end())return it-nums.begin();
nums.push_back(target);
sort(nums.begin(),nums.end());
return find(nums.begin(),nums.end(),target)-nums.begin();
}
};
方法二:
其实这个题是寻找target合适的位置,只要找到大于等于他的位置,要么是他的位置,要么是他将要插入的位置。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
for(int i=0;i<nums.size();i++)
if (nums[i]>=target)return i;
return nums.size();
}
};
方法三:
二分查找,时间复杂度O(n)变为O(logn)。这道题想要考察的应该就是二分查找。
二分查找的思想就是先取一个中间的数,进行比较,然后缩小区间,等。如果没找到,left就是刚好比target大一点的索引;
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left=0, right=nums.size()-1, mid;
while (left <= right) {
mid = (left + right) / 2;
if (target == nums[mid])return mid;
else if (target < nums[mid])right = mid - 1;
else left = mid + 1;
}
return left;
}
};
53. 最大子序和
这道题有些难度。
方法一:动态规划
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int sum=0;
int a;
int ans=nums[0];
for(int i=0;i<nums.size();i++){
a=nums[i];
if(sum>0)sum+=a;
else sum=a;
ans=ans>sum?ans:sum; //这一行很重要,加上这个才能得到全局最优
}
return ans;
}
};
暴力、贪心、分治 等方法还有很多,有必要都看一看。
66. 加一
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
解法一:
首先要取到数组的最后一位数,相加后的和即为sum. Sum的余数放在这一位,sun/10应该和前一位相加,直到为0的时候停止。
但是要考虑到,第一个数只加一,后面的数只加产生的进位,和第一个数也有进位这种情况。
class Solution {
public:
vector<int> plusOne(vector<int>& digits) {
int sum=0;
int i=digits.size()-1;
digits[i]+=1;
while(i>=0){
sum+=digits[i];
digits[i]=sum%10;
if(sum/10==0)return digits;
else {
i--;
sum/=10;
}
}
if(i<0) digits.insert(digits.begin(), sum);
return digits;
}
};
解法二:递归?
本题中最后一个数只加一,产生的进位最大也只是1;所以,递归的跳出条件是,传入的数组末尾加一无进位,就返回这个数组。或者已经到达了数组的开头,就插入然后返回数组。
class Solution {
public:
vector<int> plusOne(vector<int>& digits) {
int i=digits.size()-1;
return F(digits, i);
}
vector<int> F(vector<int>& digits, int i) {
if(digits[i]+1>9){
digits[i]=(digits[i]+1)%10;
if(i==0){
digits.insert(digits.begin(), 1);
return digits;
}
else return F(digits, i-1);
}
else{
digits[i]=(digits[i]+1);
return digits;
}
}
};
方法三:
如果是9这一位置为0,否则返回本位加1后的数组。
class Solution {
public:
vector<int> plusOne(vector<int>& digits) {
for(int i=digits.size()-1;i>=0;i--){
if(digits[i]==9)digits[i]=0;
else {
digits[i]++;
return digits;
}
}
digits.insert(digits.begin(),1);
return digits;
}
};
88. 合并两个有序数组
给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 num1 成为一个有序数组。
解法一:
有些麻烦的解法,就是比较开头的两个大小,插入,数组2指针右移。不插入,数组1指针右移。
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i=0, j=0;
while(j<n){
if(i>=m)while(j<n)nums1[i++]=nums2[j++];
else if(nums1[i]<=nums2[j])i++;
else {
nums1.insert(nums1.begin()+i,nums2[j]);
nums1.pop_back();
m++;
j++;
}
}
}
};
方法二:
假装有第三个数组,每次在数组1、2中选择一个小的复制进来。但是为了节约空间,不复制num1,就从num1的尾巴开始。
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int p1=m-1,p2=n-1,q=m+n-1;
while(p1>=0&&p2>=0)
nums1[q--]=nums1[p1]>nums2[p2]?nums1[p1--]:nums2[p2--];
while(p2>=0)nums1[q--]=nums2[p2--];
}
};
方法三:
把数组2替换掉数组1里的0,然后.sort()排序。这样就不能利用数组有序这一点。
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
nums1.insert(nums1.begin()+m, nums2.begin(),nums2.end());
nums1.resize(m+n);
// copy(nums2.begin(),nums2.end(),nums1.begin() + m);
sort(nums1.begin(),nums1.end());
}
};
118. 杨辉三角
解法一:
先把向量的每一行初始化为1,每一行的列数都和第几行相等,由此可以进行初始化;
然后从第二列开始,用上一行的两个数相加计算。嵌套两个for循环可以完成。
class Solution {
public:
vector<vector<int>> generate(int numRows) {
vector<vector<int>> re(numRows);
for(int i=0;i<numRows;i++){
re[i].resize(i+1,1);
for(int j=1;j<i;j++)
re[i][j]=re[i-1][j-1]+re[i-1][j];
}
return re;
}
};
如果不先把每一行初始化成1,可以增加一个判断,第一列和最后一列re[i].push_back(1)
数组部分的题目就先到这里结束了,下一篇文章是关于字符串的简单题目