1.和为k的子数组
给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
示例 1 :
输入:nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/subarray-sum-equals-k
方法一:暴力枚举:两层循环,第一层start从0-len-1,第二层end从start到0,这样可以遍历所有的数组.
class Solution { public: int subarraySum(vector<int>& nums, int k) { int len=nums.size(); int count=0; for(int start=0;start<len;start++)//0-len-1 { int sum=0; for(int end=start;end>=0;end--)//start-0 { sum+=nums[end]; if(sum==k) { count++; } } } return count; } };
方法二:前缀和+哈希表优化:key是前缀和,value是这个前缀和出现了几次。根据当前前缀和,在 map 中寻找【相减 === k】的目标前缀和。目标前缀和是一个数值,出现这个数值可能不止 1 次,假设为 n 次,就等价于,找到 n 个连续子数组的求和 === k,遍历 nums 数组,不断把 n 累加给 count,最后返回count
class Solution { public: int subarraySum(vector<int>& nums, int k) { unordered_map<int, int> mp; mp[0] = 1; int count = 0, pre = 0; for (auto& x:nums) { pre += x; if (mp.find(pre - k) != mp.end()) count += mp[pre - k];//找到对应key值pre-k,count++ mp[pre]++;//value++ } return count; } };
2.和为s的连续正数序列。
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序。
class Solution { public: vector<vector<int> > FindContinuousSequence(int sum) { vector<vector<int>> res; vector<int> cur; if(sum<3) return res; int small=1,big=2; int num=small+big;//记录当前序列值 while(small<(sum+1)/2)//因为序列至少要两个数字 { if(num==sum) { for(int i=small;i<=big;i++) { cur.push_back(i); } res.push_back(cur); cur.clear(); } while((num>sum)&&(small<(sum+1)/2))//需要减短序列 { num-=small; small++; if((num==sum)&&(small<(sum+1)/2)) { for(int i=small;i<=big;i++) { cur.push_back(i); } res.push_back(cur); cur.clear(); } } big++; num+=big; } return res; } };
3.和为s的两个数字。
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
思路:双指针,一个在左一个在右,相向查找,因为两个数离得越远乘积越小,因此可以最快找到最小的适合值。
class Solution { public: vector<int> FindNumbersWithSum(vector<int> array,int sum) { int len=array.size(); vector<int> res; if(len<=1) return res; int left=0; int right=len-1; while(left<right) { if(array[left]+array[right]==sum) { res.push_back(array[left]); res.push_back(array[right]); return res; } else if(array[left]+array[right]<sum) { left++; } else { right--; } } return res; } };
4.左旋转字符串
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!
思路:先翻转前面的n为字符,再翻转n位之后的所有字符,最后整体翻转。
class Solution { public: string LeftRotateString(string str, int n) { int len=str.length(); if(len<2) return str; n%=len;//可能左移次数大于长度 if(n>0&&n<len) { int firstStart=0; int firsrEnd=n-1; int secondStart=n; int secondEnd=len-1; exChange(str,firstStart,firsrEnd);//先移动前面n位 exChange(str,secondStart,secondEnd);//再移动n位后面的所有字符 exChange(str,0,len-1);//整体翻转 } return str; } void exChange(string &str, int s, int e)//记得加引用 { while(s < e) swap(str[s++], str[e--]); } };