给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
链接:https://leetcode-cn.com/problems/two-sum
/*基本思想:使用一个哈希表来解,第一遍扫描,保存到哈希表中,第二遍扫,看target-n在不在哈希表中,时间复杂度为O(n)。
其实就是模拟python的in 查找是否在里面
*/
c++解法
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
map<int, int> mapping;
vector<int> res;
for (int i = 0; i < nums.size(); ++i) {
mapping[nums[i]] = i;
}
for (int i = 0; i < nums.size(); i++) {
int searched = target - nums[i];
if (mapping.find(searched) != mapping.end() && i != mapping[searched]) {
res.push_back(i);
res.push_back(mapping[searched]);
break;
}
}
return res;
}
};
python解法
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
index1 = 0
while index1<len(nums):
rest = target - nums[index1]
for i in range(index1+1,len(nums)):
if nums[i] == rest:
index2 = i
return index1,index2
index1+=1;
return []
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
链接:https://leetcode-cn.com/problems/3sum
/*基本思想:使用dfs暴力会时间超限,所以思想就是利用双指针,先对数组排序 对于每一个数i,双指针指向i+1和尾,和==0 继续,和<0,l++,和>0,r--
注意=0的时候加入结果需要判断重复,可以使用set去重
特殊情况:全是0的时候也会时间超限,所以可以直接在循环数组的时候,如果i和前一个相同,就不进行操作了
*/
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>>res;
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size();i++)
{
if(nums[i] > 0) break;
if(i>0 && nums[i]==nums[i-1]) // 第一个数取的时候去重
continue;
int left = i+1;
int right = nums.size()-1;
while(left<right)
{
vector<int>cur;
int sum = nums[i]+nums[left]+nums[right];
if(sum==0)
{
cur.push_back(nums[i]);
cur.push_back(nums[left]);
cur.push_back(nums[right]);
if(left==0 || right==nums.size()-1 || (left >0 && nums[left]!=nums[left-1]) ||( right<nums.size()-1 && nums[right] != nums[right+1])) //去重判断,也可以使用set进行去重
res.push_back(cur);
left++;
right--;
}
else if(sum<0)
left++;
else
right--;
}
}
return res;
}
};
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
链接:https://leetcode-cn.com/problems/4sum
/*基本思路:和3sum类似,只是固定两个数,然后用双指针一前一后进行逼近
*/
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> res;
set<vector<int>> s;
if(nums.size()<4)
return res;
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size()-3;i++)
{
for(int j=i+1;j<nums.size()-2;j++)
{
int left = j+1;
int right = nums.size()-1;
int sum;
while(left<right)
{
sum=nums[i]+nums[j]+nums[left]+nums[right];
if(sum==target)
{
vector<int> cur;
cur.push_back(nums[i]);
cur.push_back(nums[j]);
cur.push_back(nums[left]);
cur.push_back(nums[right]);
s.insert(cur);
left++;
right--;
}
else if(sum<target)
left++;
else
right--;
}
}
}
set<vector<int>>::iterator iter = s.begin();
for(;iter!=s.end();iter++)
{
res.push_back(*iter);
}
return res;
}
};
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
链接:https://leetcode-cn.com/problems/3sum-closest
/*
基本思想:先把数组排序,第一层循环每个数遍历一次,找后面的两个数相加,利用双指针,第二个数从i+1开始 第三个数最后开始,因为数组是有序的,所以如果和比target大,就是离target更近的应该在前面,再向后加差距就更大了 则n3--
如果比target小,同理则n2++,一样距离为0 返回target,在求出和之后更新cur就是和target距离最近的。
*/
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());
int n1;
int n2=0;
int n3=nums.size()-1;
int cur = nums[0]+nums[1]+nums[2];
for(n1=0;n1<nums.size();n1++)
{
n2=n1+1;
n3=nums.size()-1;
while(n2<n3)
{
int sum = nums[n1]+nums[n2]+nums[n3];
if(abs(sum-target) < abs(cur-target))
cur = sum;
if(sum>target)
n3--;
else if(sum<target)
n2++;
else
return target;
}
}
return cur;
}
};
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
链接:https://leetcode-cn.com/problems/plus-one
/*基本思想:记录进位就好,最后利用reverse转置
*/
class Solution {
public:
vector<int> plusOne(vector<int>& digits) {
vector<int> res;
int i=digits.size()-1;
int rest = 0;
int curnum;
curnum = (digits[i]+1)%10;
rest = (digits[i]+1)/10;
res.push_back(curnum);
for(i=digits.size()-2;i>=0;i--)
{
curnum = (digits[i]+rest)%10;
rest = (digits[i]+rest)/10;
res.push_back(curnum);
}
if(rest == 1)
res.push_back(1);
reverse(res.begin(),res.end());
return res;
}
};
给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
说明:
你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。
链接:https://leetcode-cn.com/problems/first-missing-positive/
/*基本思想:方法一:数组排序,从1开始找第一个不存在的正整数,时间复杂度为O(nlogn)
方法二:假设数组长度为n,遍历数组,数组中的值在1-n的范围内的数a放在对应的a-1的位置,如果不在就与在a-1那个位置的数交换,调整之后,遍历数组,如果这个值i所处的位置不是i-1,就返回i+1就是最小的正整数
遍历完了之后返回n+1.这相当于是数组下标+1表示正整数,存储对应下标的征整数,没有这个值就是最小的正整数,时间复杂度O(n)
*/
class Solution {
public:
/* int firstMissingPositive(vector<int>& nums) {
int res=1;
int i;
sort(nums.begin(),nums.end());
for(i=0;i<nums.size();i++)
{
if(res==nums[i])
res++;
}
return res;
}*/
int firstMissingPositive(vector<int>& nums) {
for(int i=0;i<nums.size();i++)
{
while(nums[i]<nums.size()&& nums[i]>0 &&nums[i]!=nums[nums[i]-1])
swap(nums[i],nums[nums[i]-1]);
}
int i;
for(i=0;i<nums.size();i++)
{
if(i+1!=nums[i])
return i+1;
}
return i+1;
}
};
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
注意你不能在买入股票前卖出股票。
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock
/*基本思想:方法一:直接对于每一天买入的情况,在买入的之后的每一天判断收益,收益大的就更新结果
方法二:贪心,先记录最小值,遍历碰到更小的值就更新,不小的话就计算收益,大的更新结果
*/
class Solution {
public:
/*int maxProfit(vector<int>& prices) {
int profit=0;
int i;
for(i=0;i<prices.size();i++)
{
int j=i+1;
for(;j<prices.size();j++)
{
if(prices[j]-prices[i]>profit)
profit = prices[j]-prices[i];
}
}
return profit;
}*/
int maxProfit(vector<int>& prices) {
int profit=0;
if(prices.size()==0)
return 0;
int min = prices[0];
int i;
for(i=0;i<prices.size();i++)
{
if(prices[i]<min)
min = prices[i];
else
profit = max(profit,prices[i]-min);
}
return profit;
}
};
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii
/*
基本思想:方法一:保留当前的利润,遍历,min是最小值也是买入的时候,如果遍历比min小,那就从此刻买入,加上前面的利润,重新计算利润,如果比min大,那就判断是否是最大的,计算利润判断就是后面还有没有更大的,如果没有比之前的利润大,就在此刻买入,重新计算
方法二:直接遍历一次,找连续递增的,连续递增就是利润累加,一次买入,一次卖出,最终利润是多个连续递增的累加和
*/
class Solution {
public:
/*int maxProfit(vector<int>& prices) {
if(prices.size()==0)
return 0;
int profit = 0;
int min=prices[0];
int i;
int cur_profit = 0;
for(i=1;i<prices.size();i++)
{
if(prices[i]<min){
min = prices[i];
profit+=cur_profit;
cur_profit=0;
}
else{
if(prices[i] -min>cur_profit)
{
cur_profit = prices[i] -min;
}
else
{
min = prices[i];
profit+=cur_profit;
cur_profit=0;
}
}
}
return profit+cur_profit;
}*/
int maxProfit(vector<int>& prices) {
int i;
int profit = 0;
for(i=1;i<prices.size();i++)
{
if(prices[i]>prices[i-1])
profit+=prices[i]-prices[i-1];
}
return profit;
}
};
给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。
注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii
/*基本思想:动态规划,对于第i天来说,考虑前面0-i天的最大收益和后面i-n天的最大收益,两个累加就是第i天的两次交易之后的最大收益,然后在i天中找最大的
*/
class Solution {
public:
int maxProfit(vector<int>& prices) {
if(prices.size()==0)
return 0;
vector<int> dp1(prices.size(),0); //前面i天中收益最大的,判断是第i天是否卖出,不卖出就是i-1的收益
vector<int> dp2(prices.size(),0); //后面i天中收益最大的,判断是第i天是否买入,不买入就是i+1的收益
int i;
int minval = prices[0];
for(i=1;i<prices.size();i++)
{
dp1[i] = max(prices[i]-minval,dp1[i-1]);
if(prices[i]<minval)
minval = prices[i];
}
int maxval = prices[prices.size()-1];
for(i=prices.size()-2;i>=0;i--)
{
dp2[i] = max(maxval-prices[i],dp2[i+1]);
if(prices[i]>maxval)
maxval = prices[i];
}
int Profit =0;
for(i=0;i<prices.size();i++)
{
Profit = max(Profit,dp1[i]+dp2[i]);
}
return Profit;
}
};
给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
链接:https://leetcode-cn.com/problems/remove-element
/*基本思想:
方法一:用两个下标来记录,j相当于存新的不为val的数,但是在原数组的基础上存储,不额外增加内存,i就遍历数组,找到不为val的存入j的位置。
最后j就是新的数组的长度
方法二:针对牛客的输出设置
设置前后两个游标,pre和last,分别指向数组的前后。
算法执行开始,先从last游标开始向前执行,每次遇到A[last] = elem时候,将last-1.当A[last] != elem时候,pre再从前边向后执行,
当A[pre] != elem的时候pre+1,否则将A[pre] = A[last],pre+1且last-1.
*/
class Solution {
public:
//不改变相对位置
/*int removeElement(vector<int>& nums, int val) {
int len = nums.size();
int i=0,j=0;
while(i<nums.size())
{
if(nums[i]!=val)
{
nums[j++] = nums[i];
}
i++;
}
return j;
}*/
//改变相对位置,前后指针
int removeElement(vector<int>& nums, int val)
{
int pre = 0;
int n =nums.size();
int last = n-1;
while( pre <= last)
{
if (nums[last] == val)
{
last--;
}
else {
if(nums[pre] != val)
{
pre++;
}
else
{
nums[pre] = nums[last];
pre++;
last--;
}
}
}
return last+1;
}
};
给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
链接:https://leetcode-cn.com/problems/merge-sorted-array/
/*基本思想:因为要合并到num1数组里面所以从后向前合并填写
*/
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int index = m+n-1;
int i=m-1;
int j=n-1;
while(i>=0 && j>=0)
{
if(nums1[i] <= nums2[j])
{
nums1[index--] = nums2[j];
j--;
}
else
{
nums1[index--] = nums1[i];
i--;
}
}
while(i>=0)
{
nums1[index--] = nums1[i--];
}
while(j>=0)
{
nums1[index--] = nums2[j--];
}
}
};
给定一个未排序的整数数组,找出最长连续序列的长度。
要求算法的时间复杂度为 O(n)。
示例:
输入: [100, 4, 200, 1, 3, 2]
输出: 4
解释: 最长连续序列是 [1, 2, 3, 4]。它的长度为 4。
链接:https://leetcode-cn.com/problems/longest-consecutive-sequence
/*基本思想:用到c++STL中的hash表,hash的查找和删除都是O(1)的时间复杂度,所以满足条件
只需要对于每一个数,向前找第一个不在数组中的,向后找最后一个不在的,计算比较得到最大的连续长度即可
*/
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
int res=0;
unordered_set<int> st(nums.begin(),nums.end());
for(int i=0;i<nums.size();i++)
{
int num = nums[i];
st.erase(num);
int befor=num-1;
int after=num+1;
while(st.find(befor)!=st.end())
st.erase(befor--);
while(st.find(after)!=st.end())
st.erase(after++); //不删也可以就是检查的数据多了
res = max(res,after-befor-1);
}
return res;
}
};
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array
/*基本思想:双指针i,j都指向数组,然后用i的数赋值在j的位置(和移除某个元素的思想一样)
*/
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size()==0)
return 0;
int i=1,j=1;
while(i<nums.size())
{
if(nums[i]!=nums[i-1])
{
nums[j++]=nums[i];
}
i++;
}
return j;
}
};
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array-ii
/*基本思想:还是两个指针,但是i直接和j-2的位置比较,相等就表示已经存在两个了,不等情况下再放入
*/
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size()<=2 )
return nums.size();
int i=2,j=2;
while(i<nums.size())
{
if(nums[i] != nums[j-2])
nums[j++] = nums[i];
i++;
}
return j;
}
};
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/submissions/
/*基本思想: 方法一:将两个数组合并,找中位数,但是时间复杂度不符合要求
方法二:二分查找,转化为找两个有序数组中第k个元素,并且采用二分法搜索第k个元素,每次查找第k/2个元素,对于两个数组,确定每次搜索的范围数组中到底存不存在第K/2个数字,如果存在就取出来,否则就赋值上一个整型最大值。如果某个数组没有第K/2个数字,那么我们就淘汰另一个数字的前K/2个数字即可。有没有可能两个数组都不存在第K/2个数字呢,这道题里是不可能的,因为我们的K不是任意给的,而是给的m+n的中间值,所以必定至少会有一个数组是存在第K/2个数字的。最后就是二分法的核心啦,比较这两个数组的第K/2小的数字midVal1和midVal2的大小,如果第一个数组的第K/2个数字小的话,那么说明第一个数组前k/2个元素在合并之后一定在k之前,一定不是第k个元素,所以我们可以将其淘汰,将nums1的起始位置向后移动K/2个,并且此时的K也自减去K/2,调用递归。反之,我们淘汰nums2中的前K/2个数字,并将nums2的起始位置向后移动K/2个,并且此时的K也自减去K/2,调用递归即可。
*/
class Solution {
public:
/* double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int i=0,j=0;
vector<int> res;
int m=nums1.size();
int n=nums2.size();
while(i<nums1.size() && j<nums2.size())
{
if(nums1[i] <= nums2[j])
{res.push_back(nums1[i]);
i++;
}
else
{
res.push_back(nums2[j]);
j++;
}
}
while(i<nums1.size())
{
res.push_back(nums1[i]);
i++;
}
while(j<nums2.size())
{
res.push_back(nums2[j]);
j++;
}
if((m+n)%2==0)
return (double)(res[(m+n)/2-1]+res[(m+n)/2])/2;
else
return res[(m+n)/2];
}*/
int findKth(vector<int>& nums1, int i,vector<int>& nums2 ,int j,int k){
if( i >= nums1.size()) return nums2[j + k - 1];//nums1为空数组
if( j >= nums2.size()) return nums1[i + k - 1];//nums2为空数组
if(k == 1){
return min(nums1[i], nums2[j]);
}
int midVal1 = (i + k / 2 - 1 < nums1.size()) ? nums1[i + k / 2 - 1] : INT_MAX;
int midVal2 = (j + k / 2 - 1 < nums2.size()) ? nums2[j + k / 2 - 1] : INT_MAX;
if(midVal1 < midVal2){
return findKth(nums1, i + k / 2, nums2, j , k - k / 2);
}else{
return findKth(nums1, i, nums2, j + k / 2 , k - k / 2);
}
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size();
int n = nums2.size();
int left = (m + n + 1) / 2;
int right = (m + n + 2) / 2;
return (findKth(nums1, 0, nums2, 0, left) + findKth(nums1, 0, nums2, 0, right)) / 2.0;
}
};
给定整数数组 A,每次 move 操作将会选择任意 A[i]
,并将其递增 1
。
返回使 A
中的每个值都是唯一的最少操作次数。
链接:https://leetcode-cn.com/problems/minimum-increment-to-make-array-unique/
/*
基本思路:
方法一:空间换时间 每个数最大为40000,那么相加最大80000,开辟一个数组,遍历原数组,对应的值放到对应下标的位置,如果放过了,那就线性向后放(向后的次数也就是move的次数)
方法二: 先排序,每次比较和前一个数的关系,不大,那就赋值为比他大的第一个,move也就是他俩的差加一,统计所有的关系即可
*/
class Solution {
public:
/*
int minIncrementForUnique(vector<int>& A) {
int nums[80000] ;
memset(nums, -1, 80000*sizeof(int));
int count = 0;
for(int i=0;i<A.size();i++)
{
int index = A[i];
if(nums[index] != index)
{
nums[index] = index;
}
else
{
while(nums[index] == index)
{
count++;
index++;
}
nums[index] = index;
}
}
return count;
}
*/
int minIncrementForUnique(vector<int>& A) {
sort(A.begin(),A.end());
int count = 0;
for(int i=1;i<A.size();i++)
{
if (A[i] <= A[i-1])
{
count+= A[i-1] - A[i] + 1 ;
A[i] =A[i-1]+1;
}
}
return count;
}
};
给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次。
找到所有在 [1, n] 范围之间没有出现在数组中的数字。
链接:https://leetcode-cn.com/problems/find-all-numbers-disappeared-in-an-array
/*基本思想: 方法一:把数字都放到自己对应的位置上,如果当前i不满足放在正确位置上,看正确位置是他说明重复,那这个i地方置为-1,表示空,否则就交换到正确位置,满足条件或者本身为-1就继续,最后遍历判断值为-1的位置就是消失的数字
方法二: 原地哈希,对于每一个出现的数,把他对应的位置置为对应的负数,没有被置为负数就是消失的数字
*/
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
vector<int> res;
for(int i=0;i<nums.size();i++)
{
if(nums[abs(nums[i])-1]>0)
nums[abs(nums[i])-1] *= -1;
}
for(int i=0;i<nums.size();i++)
{
if(nums[i]>0)
res.push_back(i+1);
}
return res;
}
/*
vector<int> findDisappearedNumbers(vector<int>& nums) {
vector<int> res;
int i=0;
while(i<nums.size())
{
if(nums[i]==-1 || nums[i]==i+1 )
{ i++;
continue;
}
if(nums[nums[i]-1] == nums[i])
{
nums[i] = -1;
i++;
continue;
}
swap(nums[i], nums[nums[i]-1]);
}
for(int i=0;i<nums.size();i++)
{
if(nums[i] == -1)
res.push_back(i+1);
}
return res;
}
*/
};
给你一个未排序的整数数组,请你找出其中没有出现的最小的正整数。
链接:https://leetcode-cn.com/problems/first-missing-positive/
/*基本思想:正确的数放到正确的位置,小于0和大于数组长度的数不交换,注意最小正数一定在1-n+1之间 只有在两个数不相等的时候交换才会避免死循环
*/
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int i=0;
while(i<nums.size())
{
if(nums[i] != i+1 && 0<nums[i] && nums[i]<nums.size() && nums[i] != nums[nums[i]-1])
swap(nums[i],nums[nums[i]-1]);
else
i++;
}
int res = nums.size()+1;
for(int i=0;i<nums.size();i++)
{
if(nums[i] != i+1)
return i+1;
}
return res;
}
};
给定一个整数数组 a,其中1 ≤ a[i] ≤ n (n为数组长度), 其中有些元素出现两次而其他元素出现一次。
找到所有出现两次的元素。
链接:https://leetcode-cn.com/problems/find-all-duplicates-in-an-array/
/*基本思路: 方法一:对应的数放到正确的位置上,如果不在正确位置,判断正确位置的数正确,则说明重复就作为返回结果,否则就交换,注意有重复的话,就设置一个-1表示这个数已经不需要处理了
方法二:还是对应位置的数变成负数,然后当前已经是负的说明出现过,保存为结果
*/
class Solution {
public:
/*
vector<int> findDuplicates(vector<int>& nums) {
int i=0;
vector<int> res;
while(i<nums.size())
{
if(nums[i]<0)
{
i++;
continue;
}
if(nums[i] != i+1 && nums[i] != nums[nums[i]-1])
{
swap(nums[i], nums[nums[i]-1]);
}
else if(nums[i] != i+1)
{
res.push_back(nums[i]);
nums[i] = -1;
i++;
}
else
i++;
}
return res;
}*/
vector<int> findDuplicates(vector<int>& nums) {
vector<int> res;
for(int i=0;i<nums.size();i++)
{
if(nums[abs(nums[i])-1]<0){
res.push_back(abs(nums[i]));
}
else
nums[abs(nums[i])-1] *= -1;
}
return res;
}
};
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。
链接:https://leetcode-cn.com/problems/contains-duplicate-ii
/*基本思想:利用哈希,存储下标就好
*/
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
unordered_map<int,int> m;
for(int i=0;i<nums.size();i++)
{
if(m.find(nums[i]) != m.end())
{
if(i-m[nums[i]]<=k)
return true;
else
m[nums[i]] = i;
}
else
m[nums[i]] = i;
}
return false;
}
};
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
你的算法时间复杂度必须是 O(log n) 级别。
如果数组中不存在目标值,返回 [-1, -1]。
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array
/*基本思想:二分查找,找到target然后两边搜索边界
*/
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int left=0;
int right=nums.size()-1;
int start=-1;
int end=-1;
vector<int> res;
while(left<=right)
{
cout<<left<<right<<endl;
int mid = (left+right)/2;
if(nums[mid] == target)
{
start = mid;
while(start>=0 && nums[start]==target)
start--;
res.push_back(start+1);
end = mid;
while(end<nums.size() && nums[end]==target)
end++;
res.push_back(end-1);
return res;
}
else if(nums[mid]<target){
left=mid+1;
}
else
right = mid-1;
}
res.push_back(start);
res.push_back(end);
return res;
}
};
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
链接:https://leetcode-cn.com/problems/single-number
/*基本思路:两种方法:
方法一: 数组排序,前后相同则跳过继续,不同返回
方法二:用异或,两数相同异或为0,0和其他数异或为这个数
*/
class Solution {
public:
/*
int singleNumber(vector<int>& nums) {
sort(nums.begin(),nums.end());
int i;
for(i=0;i<nums.size();i++)
{
if(i!=nums.size()-1 && nums[i]==nums[i+1])
{
i++;
continue;
}
else
return nums[i];
}
return 0;
}
*/
int singleNumber(vector<int>& nums)
{
int res=0;
for (int i=0;i<nums.size();i++){
res^=nums[i];
}
return res;
}
};
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
链接:https://leetcode-cn.com/problems/single-number-ii
/*
基本思想:方法一:数组排序,和后两个比较相同跳过,继续,不同返回
方法二:位操作,int有32位对于每一位统计,如果一个数出现3次,那这一位累计和一定是和3整除,否则取余数就是剩下的那个数,最后得到结果的每一位用或操作统计这个数
*/
class Solution {
public:
/*
int singleNumber(vector<int>& nums) {
sort(nums.begin(),nums.end());
int i;
for(i=0;i<nums.size();i++)
{
if(i!=nums.size()-1 && nums[i]==nums[i+1] && nums[i]==nums[i+2])
{
i+=2;
continue;
}
else
return nums[i];
}
return 0;
}
*/
int singleNumber(vector<int>& nums) {
int result=0;
for(int i=0;i<32;i++)
{
int bits=0;
for(int j=0;j<nums.size();j++)
{
bits+=(nums[j]>>i)&1;
}
result|=(bits%3)<<i;
}
return result;
}
};
给定一个整数数组 nums
,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。
链接:https://leetcode-cn.com/problems/single-number-iii/
/*
基本思想:先对所有的数异或,结果就是要找的两个数的异或值,可以从这值找一个非0位,因为只有两个数的该位不一样,结果才为0
这两个数一定是在这一位一个为0,一个为1,按这个标准将数组划分,这一位为1的和num1异或,为0和num2异或得到这两个数
*/
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
vector<int> result;
int num1=0,num2=0;
int res=0;
for(int i=0;i<nums.size();i++) //全部异或
{
res^=nums[i];
}
int bit_1 = 1;
while((res & 1) == 0) //取最低位第一个非0的位数
{
res >>= 1;
bit_1 <<= 1;
}
for(int i=0;i<nums.size();i++)
{
if((nums[i] & bit_1)!=0) //这一位为1的和nums1异或
num1^=nums[i];
else
num2^=nums[i];
}
result.push_back(num1);
result.push_back(num2);
return result;
}
};