赞
踩
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
class Solution{
public:
void reverseString(vector<char>& s) {
if(s.size()<=1) return;
int i=0,j=s.size()-1;
while(j>i){
swap(s[i],s[j]);
i++;
j--;
}
}
};
class Solution {
public:
void reverseString(vector<char>& s) {
if(s.size()<=1) return;
reverse(s.begin(),s.end());
}
};
class Solution{
public:
void reverseHelper(vector<char>& s,int pos,int len){
if(pos>=len/2) return;
swap(s[pos],s[len-pos-1]);
reverseHelper(s,pos+1,len);
}
void reverseString(vector<char>& s) {
if(s.size()<=1) return;
reverseHelper(s,0,s.size());
}
};
将给定的链表中每两个相邻的节点交换一次,返回链表的头指针
例如:给出1->2->3->4,你应该返回链表2->1->4->3。
你给出的算法只能使用常量级的空间。你不能修改列表中的值,只能修改节点本身。
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(!head||!head->next) return head;
ListNode* p=head;
head=p->next;
p->next=head->next;
head->next=p;
//迭代之后要和之前的链表连接起来!!!
p->next=swapPairs(p->next);
return head;
}
};
给定一个值n,请生成所有的存储值1…n.的二叉搜索树(BST)的结构
例如:给定n=3,你的程序应该给出下面五种不同的二叉搜索树
[
[1,null,3,2],
[3,2,null,1],
[3,1,null,null,2],
[2,1,3],
[1,null,2,null,3]
]
class Solution { public: vector<TreeNode*> generateTreesHelper(int start,int end){ vector<TreeNode*> Trees; if(start>end){ Trees.emplace_back(nullptr); return Trees; } for(int i=start;i<=end;i++){ vector<TreeNode*> leftTrees=generateTreesHelper(start,i-1); vector<TreeNode*> rightTrees=generateTreesHelper(i+1,end); //从左子树集合中选出一颗左子树,右边相同操作,拼接到根上 for(auto& left:leftTrees){ for(auto& right:rightTrees){ TreeNode* cur=new TreeNode(i); cur->left=left; cur->right=right; Trees.emplace_back(cur); } } } return Trees; } vector<TreeNode*> generateTrees(int n) { return generateTreesHelper(1,n); } };
class Solution {
public:
int fib(int N) {
if(0==N) return 0;
if(1==N) return 1;
return fib(N-1)+fib(N-2);
}
};
给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字符的最小子串。
示例:
输入: S = “ADOBECODEBANC”, T = “ABC”
输出: “BANC”
说明:
如果 S 中不存这样的子串,则返回空字符串 “”。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
滑动窗口算法的思路是这样:
1、我们在字符串 S 中使用双指针中的左右指针技巧,初始化 left = right = 0,把索引左闭右开区间 [left, right) 称为一个「窗口」。
2、我们先不断地增加 right 指针扩大窗口 [left, right),直到窗口中的字符串符合要求(包含了 T 中的所有字符)。
3、此时,我们停止增加 right,转而不断增加 left 指针缩小窗口 [left, right),直到窗口中的字符串不再符合要求(不包含 T 中的所有字符了)。同时,每次增加 left,我们都要更新一轮结果。
4、重复第 2 和第 3 步,直到 right 到达字符串 S 的尽头。
需要思考的问题:
1、当移动 right 扩大窗口,即加入字符时,应该更新哪些数据?
增加window计数器以及window里面的元素;
2、什么条件下,窗口应该暂停扩大,开始移动 left 缩小窗口?
当valid满足need的即所有元素都出现在窗口中;
3、当移动 left 缩小窗口,即移出字符时,应该更新哪些数据?
减少window计数器以及window里面的元素;
4、我们要的结果应该在扩大窗口时还是缩小窗口时进行更新?
应该在收缩窗口的时,且在收缩之前更新最终结果。
作者:labuladong 力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-window-substring/solution/hua-dong-chuang-kou-suan-fa-tong-yong-si-xiang-by-/
窗口中一直只有T中包含的字符,是由right和left记录S中包含T中所有字符的子串的起始
class Solution { public: string minWindow(string s, string t) { unordered_map<char,int> need,window; for(char c:t) need[c]++; int left=0,right=0; int valid=0; //记录最小覆盖子串的起始索引及长度 int start=0,len=INT_MAX; while(right<s.size()){ char c=s[right]; //窗口右移 right++; //更新窗口相关的数据 if(need.count(c)){//need中存在c对应的字符 window[c]++; if(window[c]==need[c]) valid++; } //判断左窗口是否要收缩 while(valid==need.size()){ //更新最小覆盖子串 if(right-left<len){ start=left; len=right-left; } //d记录将移出窗口的字符 char d=s[left]; left++;//窗口左移 //进行窗口内数据的一系列更新 if(need.count(d)){ if(window[d]==need[d]) valid--; window[d]--; } } } return len==INT_MAX?"":s.substr(start,len); } };
给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。
换句话说,第一个字符串的排列之一是第二个字符串的子串。
示例1:
输入: s1 = “ab” s2 = “eidbaooo”
输出: True
解释: s2 包含 s1 的排列之一 (“ba”).
示例2:
输入: s1= “ab” s2 = “eidboaoo”
输出: False
class Solution { public: bool checkInclusion(string s1, string s2) { unordered_map<char,int> need,window; for(char c:s1) need[c]++; int right=0,left=0; int valid=0; while(right<s2.size()){ char c=s2[right]; right++; if(need.count(c)){ window[c]++; if(window[c]==need[c]) valid++; } //移动 left 缩小窗口的时机是窗口大小大于 t.size() 时,应为排列嘛,显然长度应该是一样的 while(right-left>=s1.size()){ if(valid==need.size()) return true;//因为map是hush表,所以若valid==need.size(),则里面的字符一定为need里面字符的排序 char d=s2[left]; left++; if(need.count(d)){ if(window[d]==need[d]) valid--; window[d]--; } } } return false; } };
给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。
说明:字母异位词指字母相同,但排列不同的字符串。不考虑答案输出的顺序。
示例 1:
输入:s: “cbaebabacd” p: “abc”
输出:[0, 6]
解释:起始索引等于 0 的子串是 “cba”, 它是 “abc” 的字母异位词。起始索引等于 6 的子串是 “bac”, 它是 “abc” 的字母异位词。
示例 2:
输入:s: “abab” p: “ab”
输出:[0, 1, 2]
解释:起始索引等于 0 的子串是 “ab”, 它是 “ab” 的字母异位词。起始索引等于 1 的子串是 “ba”, 它是 “ab” 的字母异位词。起始索引等于 2 的子串是 “ab”, 它是 “ab” 的字母异位词。
class Solution { public: vector<int> findAnagrams(string s, string p) { unordered_map<char,int> need,window; for(char c:p) need[c]++; int left=0,right=0; int valid=0; vector<int> res; while(right<s.size()){ char c=s[right]; right++; if(need.count(c)){ window[c]++; if(window[c]==need[c]) valid++; } while(right-left>=p.size()){ if(valid==need.size()) res.emplace_back(left); char d=s[left]; left++; if(need.count(d)){ if(window[d]==need[d]) valid--; window[d]--; } } } return res; } };
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
class Solution { public: int lengthOfLongestSubstring(string s) { unordered_map<char,int> window; int left=0,right=0; int Longest=0; while(right<s.size()){ char c=s[right]; right++; window[c]++; //c在窗口中出现不止一次,证明窗口要收缩了 while(window[c]>1){ char d=s[left]; left++; window[d]--; } Longest=max(Longest,right-left); } return Longest; } };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。