数组:移除元素
字符串:反转字符串
字符串:替换空格
字符串:翻转字符串里的单词
链表:翻转链表
链表:删除链表的倒数第 N 个结点
链表:链表相交
链表:环形链表
双指针:三数之和
双指针:四数之和
三角形个数
给定一个整数数组,在该数组中,寻找三个数,分别代表三角形三条边的长度,问,可以寻找到多少组这样的三个数来组成三角形?
class Solution {
public:
int triangleCount(vector<int>& s) {
int lef,right;
int ans=0;
sort(s.begin(),s.end());
for(int i=0;i<s.size();i++){
left=0;
right=i-1;
while(left<right){
if(s[left]+s[right]>s[i]){
ans+=(right-left);
right--;
}else{
left++;
}
}
}
return ans;
}
};
class Solution {
public:
int triangleNumber(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
int ans = 0;
for (int i = 0; i < n; ++i) {
int k = i;
for (int j = i + 1; j < n; ++j) {
while (k + 1 < n && nums[k + 1] < nums[i] + nums[j]) {
++k;
}
ans += max(k - j, 0); //同上面的left<right;
}
}
return ans;
}
};
k数之和
1.求方案总数
动态规划
2.求具体方案
用深度优先搜素
数组划分
给出一个整数数组 nums 和一个整数 k。划分数组(即移动数组 nums 中的元素),使得:
所有小于k的元素移到左边
所有大于等于k的元素移到右边
返回数组划分的位置,即数组中第一个位置 i,满足 nums[i] 大于等于 k。
class Solution {
public:
int partitionArray(vector<int> &nums, int k) {
int i = 0, j = nums.size() - 1;
while (i <= j) {
while (i <= j && nums[i] < k) i++;
while (i <= j && nums[j] >= k) j--;
if (i <= j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
i++;
j--;
}
}
return i;
}
};
交错正负数
给出一个含有正整数和负整数的数组,重新排列成一个正负数交错的数组。
class Solution {
public:
void partition(vector<int>& nums,bool start_positive){
int flag;
if (start_positive){
flag=1;
}else{
flag=-1;
}
int left=0,right=nums.size()-1;
while(left<=right){
while(left<=right&&nums[left]*flag>0){
left+=1;
}
while(left<=right&&nums[right]*flag<=0){
right--;
}
if(left<=right){
swap(nums[left],nums[right]);
left+=1;
right-=1;
}
}
}
void interleave(vector<int>& nums,bool has_same_length){
int left=1,right=nums.size()-1;
if(has_same_length) right=nums.size()-2;
while(left<right){
swap(nums[left],nums[right]);
left+=2;
right-=2;
}
}
void rerange(vector<int> &nums) {
int positive = 0;
int negitive = 0;
for(auto i:nums)
{
if(i > 0)
positive++;
else
negitive++;
}
partition(nums,positive>negitive);
interleave(nums,positive==negitive);
}
};
颜色分类
给定一个包含红,白,蓝且长度为 n 的数组,将数组元素进行分类使相同颜色的元素相邻,并按照红、白、蓝的顺序进行排序。
我们使用整数 0,1 和 2 分别代表红,白,蓝。
class Solution{
public:
void sortColors(vector<int> &nums) {
int left = 0, right = nums.size() - 1;
int middle = 0;
// should be <= not <
while (middle <= right) {
if (nums[middle] == 0) {
swap(nums[middle], nums[left]);
left++;
middle++;
} else if (nums[middle] == 1) {
middle++;
} else {
swap(nums[middle], nums[right]);
right--;
}
}
}
};
彩虹排序
给定一个有n个对象(包括k种不同的颜色,并按照1到k进行编号)的数组,将对象进行分类使相同颜色的对象相邻,并按照1,2,…k的顺序进行排序。
class Solution {
public:
void sortColors2(vector<int> &colors, int k) {
if (colors.size() < 2) {
return;
}
sort(colors, 0, colors.size() - 1, 1, k);
}
void sort(vector<int> &colors, int start, int end, int colorFrom, int colorTo) {
//若处理区间长度为小于等于1或颜色区间长度为1,则不需要再进行处理
if (start >= end || colorFrom == colorTo) {
return;
}
//设置左右指针以及中间的颜色
int left = start;
int right = end;
int colorMid = colorFrom + (colorTo - colorFrom) / 2;
while (left <= right) {
//找到左侧大于中间颜色的位置
while (left <= right && colors[left] <= colorMid) {
left++;
}
//找到右侧小于等于中间颜色的位置
while (left <= right && colors[right] > colorMid) {
right--;
}
//交换左右指针指向的颜色
if (left <= right) {
int temp = colors[left];
colors[left] = colors[right];
colors[right] = temp;
}
}
//继续递归处理左右两半序列
sort(colors, start, right, colorFrom, colorMid);
sort(colors, left, end, colorMid + 1, colorTo);
}
};
移动零
给一个数组 nums 写一个函数将 0 移动到数组的最后面,非零元素保持原数组的顺序
class Solution {
public:
/**
* @param nums: an integer array
* @return: nothing
*/
void moveZeroes(vector<int> &nums) {
// 将两个指针先指向数组头部
int left = 0, right = 0;
while (right < nums.size()) {
// 遇到非0数赋值给新数组指针指向的位置
if (nums[right] != 0) {
nums[left] = nums[right];
// 将left向后移动一位
left++;
}
right++;
}
// 若新数组指针还未指向尾部,将剩余数组赋值为0
while (left < nums.size()) {
nums[left] = 0;
left++;
}
}
};
同向双指针
两数之差
给定一个排序后的整数数组,找到两个数的 差 等于目标值。
你需要返回一个包含两个数字的列表 [num1, num2], 使得 num1 与 num2 的差为 target,同时 num1 必须小于 num2。
保证只有一个答案。
注意:要求用O(1)空间复杂度完成。
class Solution {
public:
vector<int> twoSum7(vector<int> &nums, int target) {
vector<int> result;
if(nums.size()<2){
return result;
}
target=abs(target);
int right=1;
for(int left=0;left<nums.size();left++){
right=max(right,left+1);
while(right<nums.size()&&nums[right]-nums[left]<target){
right++;
}
if(right>nums.size()){
break;
}
if(nums[right]-nums[left]==target){
result.push_back(nums[left]);
result.push_back(nums[right]);
return result;
}
}
return result;
}
};
全零子串的数量
给出一个只包含0或1的字符串str,请返回这个字符串中全为0的子字符串的个数
class Solution {
public:
int stringCount(string &str) {
if(str.size()==0){
return 0;
}
int right=1,answer=0;
for(int left=0;left<str.size();left++){
if(str[left]!='0'){
continue;
}
right=max(right,left+1);
while(right<str.size()&&str[right]=='0'){
right++;
}
answer+=right-left;
}
return answer;
}
};
去除重复元素
给一个整数数组,去除重复的元素。
你应该做这些事
1.在原数组上操作
2.将去除重复之后的元素放在数组的开头
3.返回去除重复元素之后的元素个数
class Solution {
public:
int deduplication(vector<int> &nums) {
if(nums.size()==0){
return 0;
}
sort(nums.begin(),nums.end());
int left;
int right=1;
for(left=0;left<nums.size();left++){
while(right<nums.size()&&nums[left]==nums[right]){
right++;
}
if(right>=nums.size()){
break;
}
nums[left+1]=nums[right];
}
return left+1;
}
};
滑动窗口内数的和
给你一个大小为n的整型数组和一个大小为k的滑动窗口,将滑动窗口从头移到尾,输出从开始到结束每一个时刻滑动窗口内的数的和。
class Solution {
public:
vector<int> winSum(vector<int> &nums, int k) {
vector<int> result;
if(nums.size()<k||k==0){
return result;
}
int right=0;
int sum=0;
for(int left=0;left<nums.size();left++){
while(right<nums.size()&&right-left<k){
sum+=nums[right];
right++;
}
if(right-left==k){
result.push_back(sum);
}
sum-=nums[left];
}
return result;
}
};
快慢指针
带环链表
给定一个链表,判断它是否有环。
class Solution{
public:
bool hasCycle(ListNode * head) {
if(head==nullptr||head->next==nullptr){
return false;
}
ListNode* fast=head;
ListNode* slow=head;
while(fast!=NULL&&fast->next!=NULL){
fast=fast->next->next;
slow=slow->next;
if(slow==fast){
while(head!=slow){
head=head->next;
slow=slow->next;
}
return true;
}
}
return false;
}
};
class Solution {
public:
bool hasCycle(ListNode * head) {
if(head==nullptr||head->next==nullptr){
return false;
}
ListNode* fast=head->next;
ListNode* slow=head;
while(fast!=slow){
if(fast==nullptr||fast->next==nullptr){
return false;
}
fast=fast->next->next;
slow=slow->next;
}
while(head!=slow->next){
head=head->next;
slow=slow->next;
}
return true;
}
};
K次替换后的最长重复字符
给定一个仅包含大写英文字母的字符串,您可以将字符串中的任何一个字母替换为的另一个字母,最多替换k次。 执行上述操作后,找到最长的,只含有同一字母的子字符串的长度。
class Solution {
public:
/*
int get_max_count(unordered_map<char, int> &char2count) {
int max_count = 0;
for (auto it : char2count) {
if (it.second > max_count) {
max_count = it.second;
}
}
return max_count;
}
*/
int characterReplacement(string &s, int k) {
if(s.size()==0){
return 0;
}
int right=0;
int maxFreq=0;
unordered_map<char,int> counter;
int answer=0;
for(int left=0;left<s.size();left++){
while(right<s.size()&&right-left-maxFreq<=k){
counter[s[right]]++;
maxFreq=max(maxFreq,counter[s[right]]);
right++;
}
if(right-left-maxFreq>k){
answer=max(answer,right-left-1);
}else{
answer=max(answer,right-left);
}
counter[s[left]]--;
//maxFreq=get_max_count(counter);
}
return answer;
}
};