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--]);
}
};
京公网安备 11010502036488号