7月保研的夏令营已经告一段落了,面试中被问了很多算法的问题,感觉自己算法知识有些许薄弱(acm大神忽略),所以准备开始刷leetcode,顺便也为面试准备,因为想把刷leet里面的一些心得给记下来,便于之后复习,所以在这里开博。之后会按里面的篇章顺序进行更新,喜欢的可以给文章点一个赞,如果文章有任何问题或者有更好的解法可以在评论中给出,下面开始题解,本篇章为初级算法的数组篇(1-5题):
题目要求:给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
算法说明:这题是简单题,题目中要求要用O(1)的空间复杂度,所以是不能额外建一个数组了,我的思路是建一个temp等于第一个数,再建一个res变量用于存储不同的元素个数,因为数组是排序的,所以对数组进行扫描,若扫描的值和temp不一样,则更新temp并且res++,把不一样的元素移到对应的位置num[res-1]。
其代码如下:
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int res=1;
int curser;
if(nums.size()==0){
return 0;
}
int temp=nums[0];
for(int i=0;iif(nums[i]!=temp){
res++;
temp=nums[i];
nums[res-1]=nums[i];
}
else{
}
}
return res;
}
};
题目说明:给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
算法:本题就是一题贪心,当后一天的价格比之前高就卖出,具体为什么可以自己仔细想一想。
代码如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int sum=0;
if(prices.size()==1||prices.size()==0){
return 0;
}
for(int i=0;i1;i++){
if(prices[i+1]>prices[i]){
sum=sum+prices[i+1]-prices[i]; }
}
return sum;
}
};
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入: [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]
尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
要求使用空间复杂度为 O(1) 的原地算法。
该题的解法有很多,这里给出三种空间为O(1)的方法。
方法一:写一个旋转一次的函数,然后根据题目要求的k,旋转k次,这样空间复杂度为O(1),时间复杂度为O(N^K)。
方法二:和上个方法类似,不过移动的时候直接通过nums[i]与nums[(i+k)%nums.size()]这样对应,从而减少操作次数。空间复杂度O(1),时间复杂度O(N)。
方法三:这是另一个比较好的方法,建立一个变量times=k%n。然后对于一个数组从times开始把整个数组分为两个部分。如[1,2,3,4,5,6,7] 和 k = 3,此时n=7。times=3。则把[1,2,3,4,5,6,7]分成两个部分[1,2,3,4 | 5,6,7],然后把第一个部分翻转[4,3,2,1 | 7,6,5],把第二部分也翻转[4,3,2,1 | 7,6,5],最后把整个数组翻转得到最终答案[5,6,7,1,2,3,4],该方法时间复杂度O(n)。
该方法的代码如下:
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int n=nums.size();
int times=k%n;
if(times==0)
return;
rotCore(nums,0,n-1-times);
rotCore(nums,n-times,n-1);
rotCore(nums,0,n-1);
}
void rotCore(vector<int>& nums,int b,int e){
while(breturn;
}
};
题目描述:给定一个整数数组,判断是否存在重复元素。如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。
算法说明:这题和第一题的不同之处在于不是有序的数组。方法1通过对每个元素判断是否有重复,时间复杂度O(n^2)。所以这里我采用了set容器,扫描的过程中把元素加入,如果有重复就返回true,因为set容器中的查找为红黑树,所以该方法的时间复杂度为O(nlogn)。代码如下:
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
set<int> table;
int i;
for(i=0;iif(table.count(nums[i])==1) return true;
table.insert(nums[i]);
}
return false;
}
};
题目说明:给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
算法说明:这道题目是面试中的原题了,有同学面试被问到过,难度在于线性时间复杂度和不使用额外空间,要满足这两个条件的本题的方法是使用异或。
首先我们知道异或对与一样的两个数他们的结果会是0,而且异或符合交换律,所以把数组中所有的数异或一遍就得到了结果,而且符合了线性复杂度和0额外空间,其代码如下:
class Solution {
public:
int singleNumber(vector<int>& nums) {
int m=0;
for(int i=0;ireturn m;
}
};
6-11题的题解马上也会更新