这里写目录标题
力扣15三数之和
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
示例 3:
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。
提示:
3 <= nums.length <= 3000
-105 <= nums[i] <= 105
题目分析
找出相加为0的三元组,每个三元组不能重复
解题思路
直接暴力枚举三层循环会超出时间限制
首先定义一个新的二维数组用于输出,并从小到大排列数组
然后第一层for循环先找出一个值,则能确定另外两个值的和,注意枚举时的去重,去掉nums[i]==nums[i+1]时的值,而不是nums[i]==nums[j]时的值
最后进行剪枝操作,因为已经将数组重排序,所以当值大于目标值时,对于第三层指针,只需将其左移,就可以快速定位
代码实现
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>>ans;//定义一个新的二维数组用于输出
sort(nums.begin(),nums.end());//从小到大排列
for(int i=0;i<nums.size();i++)
{
if(i>0&&nums[i]==nums[i-1])//必须有i>0的条件,是为了判断与上一个枚举的值不同
{
continue;//因为重新排序了 所以这一步可以排除重复的nums[i]值的问题
}
int t=-nums[i];
int k=nums.size()-1;
for(int j=i+1;j<nums.size();j++)
{
if(j>i+1&&nums[j]==nums[j-1])//必须有j+1的条件,道理同上,当nums[i]==nums[j]时,不用跳过此次循环
{
continue;
}
while(j<k&&nums[j]+nums[k]>t)//当值大于目标值时,对于k指针,只需将其左移,快速定位
{
--k;
}
if(j==k)break;//j,k指针相遇就跳出
if(nums[j]+nums[k]==t)
{
ans.push_back({nums[i],nums[j],nums[k]});//要用{}
}
}
}
return ans;
}
};
力扣2810故障键盘
你的笔记本键盘存在故障,每当你在上面输入字符 ‘i’ 时,它会反转你所写的字符串。而输入其他字符则可以正常工作。
给你一个下标从 0 开始的字符串 s ,请你用故障键盘依次输入每个字符。
返回最终笔记本屏幕上输出的字符串。
示例 1:
输入:s = “string”
输出:“rtsng”
解释:
输入第 1 个字符后,屏幕上的文本是:“s” 。
输入第 2 个字符后,屏幕上的文本是:“st” 。
输入第 3 个字符后,屏幕上的文本是:“str” 。
因为第 4 个字符是 ‘i’ ,屏幕上的文本被反转,变成 “rts” 。
输入第 5 个字符后,屏幕上的文本是:“rtsn” 。
输入第 6 个字符后,屏幕上的文本是: “rtsng” 。
因此,返回 “rtsng” 。
示例 2:
输入:s = “poiinter”
输出:“ponter”
解释:
输入第 1 个字符后,屏幕上的文本是:“p” 。
输入第 2 个字符后,屏幕上的文本是:“po” 。
因为第 3 个字符是 ‘i’ ,屏幕上的文本被反转,变成 “op” 。
因为第 4 个字符是 ‘i’ ,屏幕上的文本被反转,变成 “po” 。
输入第 5 个字符后,屏幕上的文本是:“pon” 。
输入第 6 个字符后,屏幕上的文本是:“pont” 。
输入第 7 个字符后,屏幕上的文本是:“ponte” 。
输入第 8 个字符后,屏幕上的文本是:“ponter” 。
因此,返回 “ponter” 。
提示:
1 <= s.length <= 100
s 由小写英文字母组成
s[0] != ‘i’
题目分析
逐个输入字符串,当字符为i时反转前面的字符串,注意不输入i
解题思路
如果字符为i,利用for循环覆盖i,覆盖后字符串长度-1,并在最后截取字符串加’\0’,否则会多次出现最后一个元素,然后交换’i’前字符串
如果字符不是’i’,记录字符个数用于交换,再进行输入
代码实现
char* finalString(char* s) {
int j=0;
int y=strlen(s);
for(int i=0;i<y;i++)
{
if(s[i]=='i')
{
int o=i;
for(o=i;o<y-1;o++)
{
s[o]=s[o+1];
}
s[o]='\0';//覆盖后要加'\0'
i--;//因为覆盖了一个字母 所以要将遍历数字减一
for(int k=0,p=j-1;k<p;k++,p--)
{
int q;
q=s[k];
s[k]=s[p];
s[p]=q;
}
}else{
j++;
}
}
return s;
}
力扣21合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 1:
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
示例 2:
输入:l1 = [], l2 = []
输出:[]
示例 3:
输入:l1 = [], l2 = [0]
输出:[0]
提示:
两个链表的节点数目范围是 [0, 50]
-100 <= Node.val <= 100
l1 和 l2 均按 非递减顺序 排列
题目分析
将两个有序链表合并为一个有序链表
解题思路
另外定义新链表,依次比较两个链表的值再存入
或直接使用递归将其拼接
问题:使用递归将返回l1还是l2呢?
随着递归使用,当有一个链表为空时,返回另外一个
注意:最后的判断条件不可为l1->val>=l2->next,因为必须要进入if else 语句,否则没有返回值,编译报错
如果新建链表则没有此问题
代码实现
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1==NULL)
{
return l2;
}else if(l2==NULL)
{
return l1;
}else if(l1->val<l2->val)
{
l1->next=mergeTwoLists(l1->next,l2);
return l1;
}else //不能写l1->next>=l2->next
{
l2->next=mergeTwoLists(l1,l2->next);
return l2;
}
}
};
力扣LCR086分割回文串
给定一个字符串 s ,请将 s 分割成一些子串,使每个子串都是 回文串 ,返回 s 所有可能的分割方案。
回文串 是正着读和反着读都一样的字符串。
示例 1:
输入:s = “google”
输出:[[“g”,“o”,“o”,“g”,“l”,“e”],[“g”,“oo”,“g”,“l”,“e”],[“goog”,“l”,“e”]]
示例 2:
输入:s = “aab”
输出:[[“a”,“a”,“b”],[“aa”,“b”]]
示例 3:
输入:s = “a”
输出:[[“a”]]
提示:
1 <= s.length <= 16
s 仅由小写英文字母组成
题目分析
将一个大字符串分割成n个部分,输出所有子串都是回文串的部分,回文串就是左右对称的字符串
解题思路
问题类似于回溯的思想,将一个大问题分割成n个小问题,分而治之
首先设置两个函数,一个利用递归来输出分割后的回文串另一个用于判断是否为回文串,然后主体代码设置两个字符串cur,ret,ret用来存放分割好的字符串cur用来存放不断分割好的字符串
递归的实现:以google为例
先进入第一次for循环,g在pdhw函数中为真,进入if语句,另外定义一个字符串str临时存放回文串,再将str放到cur中
注意此时再次进入helper函数,此时改变起始位置为i+1,从o开始,执行过程与上述一致,i继续加1直到i==s的长度,将cur放到ret里,跳出递归,执行cur.popback,删去分割好的字符串,回溯到初始状态index=0,cur为空
然后再次进入第二次for循环,i为1,go不符合条件,直到goog的pdhw为真再次进入,与上述过程相同
最后返回ret即可
代码实现
class Solution {
private:
void helper(string&s,int index,vector<vector<string>>&ret,vector<string>&cur){
if(index==s.size())//跳出条件
{
ret.push_back(cur);
return;
}
for(int i=index;i<s.size();i++)
{
if(pdhw(s,index,i))
{
string str=s.substr(index,i-index+1);//改变内存空间
cur.push_back(str);
helper(s,i+1,ret,cur);//后半段
cur.pop_back();//删去
}
}
}
bool pdhw(string& s,int left,int right){//判断回文
while(left<right)
{
if(s[left++]!=s[right--])
{
return false;
}
}
return true;
}
public:
vector<vector<string>> partition(string s) {
vector<vector<string>>ret;
vector<string>cur;
helper(s,0,ret,cur);
return ret;
}
};
力扣20有效的括号
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = “()”
输出:true
示例 2:
输入:s = “()[]{}”
输出:true
示例 3:
输入:s = “(]”
输出:false
提示:
1 <= s.length <= 104
s 仅由括号 ‘()[]{}’ 组成
题目分析
括号的匹配很好理解,左右对应即可,但有效的情况除了示例还可以类似{()}
解题思路
使用数组来模拟栈,定义一个数组模拟栈,当有左侧括号时,将其存放到数组中,即入栈,当有右侧括号与之对应则数组下标左移,即出栈
无效的情况分为两种:1括号位置不匹配,2没有入栈的左侧括号就存在右侧括号
代码实现
bool isValid(char* s) {
char stk[10010];
int t = -1;
for(int i = 0;i < strlen(s);i++){
if(s[i] == '(' || s[i] == '[' || s[i] == '{') stk[++t] = s[i];
else{
if(s[i] == ')'){
if(t == -1 || stk[t] != '(') return false;
else if(stk[t] == '(') t--;
}else if(s[i] == ']'){
if(t == -1 || stk[t] != '[') return false;
else if(stk[t] == '[') t--;
}else if(s[i] == '}'){
if(t == -1 || stk[t] != '{') return false;
else if(stk[t] == '{') t--;
}
}
}
return t == -1;
}
力扣14最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入:strs = [“flower”,“flow”,“flight”]
输出:“fl”
示例 2:
输入:strs = [“dog”,“racecar”,“car”]
输出:“”
解释:输入不存在公共前缀。
提示:
1 <= strs.length <= 200
0 <= strs[i].length <= 200
strs[i] 仅由小写英文字母组成
题目分析
找出字符串最长的公共的前缀,没有则返回空
解题思路
先依次比较各个字符串的第一位,然后第二位依此类推,所以要设置两层for循环,第一层控制字符串的第一位字符,第二层控制各个字符串,当前缀不为公共时,给字符串加上结尾\0,并返回
代码实现
char* longestCommonPrefix(char** strs, int strsSize) {
//**strs为二维数组,strSize为单词个数
if (strsSize == 0) {
return "";
}
//依次比较每个单词的字母
for (int i = 0; i < strlen(strs[0]); i++) {
for (int j = 1; j < strsSize; j++) {
if (strs[0][i] != strs[j][i])
{
strs[0][i] = '\0';
return strs[0];
}
}
}
return strs[0];
}