目录
Leecode-20-有效的括号
题目
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
示例
示例1
输入:s = “()”
输出:true
示例2
输入:s = “()[]{}”
输出:true
示例3
输入:s = “(]”
输出:false
解题思路
这道题可采用用数组模拟栈的方法
- 创建一个内存足够大的数组用来模拟栈,默认t为0时,栈为空
- 遍历,遇到左括号,将该符号压入栈内,遇到右括号,则继续判断,若栈为空或栈内符号与之不对应,则返回false,反之出栈
- 判断栈为空,返回true,否则返回false
代码实现
bool isValid(char* s) {
int len = strlen(s);
if (len % 2 != 0) {
return false;
}
// 用数组模拟栈
int arr[10010];
int t = 0;
for (int i = 0; i < strlen(s); i++) {
if (s[i] == '(' || s[i] == '[' || s[i] == '{') {
arr[t] = s[i];
t++;
} else {
if (s[i] == ')') {
if (t == 0 || arr[t-1] != '(') {
return false;
} else if (arr[t-1] == '(')
t--;
} else if (s[i] == ']') {
if (t == 0 || arr[t-1] != '[') {
return false;
} else if (arr[t-1] == '[')
t--;
} else if (s[i] == '}') {
if (t == 0 || arr[t-1] != '{') {
return false;
} else if (arr[t-1] == '{')
t--;
}
}
}
return t == 0;
}
Leecode-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” 。
解题思路
遍历,遇到字符i则反转’i’之前的字符,并将字符’i’之后的字符分别前移一位,输出的字符串长度应减去’i’出现的次数
代码实现
char * finalString(char * s){
int len = strlen (s), m = 0, cnt = 0;
for (int i = 0; i < len; i ++)
{
if (s[i] == 'i')
{
cnt ++;
for (int l = 0, r = i - 1; l < r; l++, r--){
char t = s[l];
s[l] = s[r];
s[r] = t;
}
for (m = i; m < len - cnt; m ++)
{
s[m] = s[m + 1];
}
s[m] = '\0';
if (s[i] == 'i') i --;
}
}
return s;
}
Leecode-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 。
解题思路
- 使用库函数
qsort
先对传入的数组元素进行排序 - 第一个for循环先确定第一个数的值,若本次的第一个数与上一次的情况相同,则跳过这个数
- 创建两个指针分别指向第一个元素的下一个元素和最后一个元素
- 若遇见符合要求的三元组,则给申请的空间赋值,若三个数之和小于0,则左边的指针右移,若三个数的之和大于0,则右边的指针往左移
- 返回res
代码实现
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int cmp(const void* pa, const void* pb){
int a=*(int*)pa;
int b=*(int*)pb;
return a>b?1:-1;
}
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) {
int **res = (int**)malloc(sizeof(int*)*50000);
*returnColumnSizes=(int*)malloc(sizeof(int)*50000);
*returnSize=0;
int l = 0,r = numsSize - 1;
//升序排序
qsort(nums,numsSize,sizeof(int),cmp);
int i,j,k;
for(i = 0; i<numsSize; i++){
if(i>0 && nums[i] == nums[i - 1]){
continue;
}
j = i + 1;
k = numsSize - 1;
while(j < k){
int sum = nums[i] + nums[j] + nums[k];
if(sum == 0){
res[*returnSize]=(int*)malloc(sizeof(int)*3);
(*returnColumnSizes)[*returnSize]=3;
res[*returnSize][0] = nums[i];
res[*returnSize][1] = nums[j];
res[*returnSize][2] = nums[k];
(*returnSize)++;
//去重
int num1 = nums[j], num2 = nums[k];
while(nums[j] == num1 && j<k){
j++;
}
while(nums[k] == num2 && j<k){
k--;
}
}else if(sum > 0){
k--;
}else {
j++;
}
}
}
return res;
}
Leecode-21-合并两个有序链表
题目
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例
示例1
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
示例2
输入:l1 = [], l2 = []
输出:[]
示例3
输入:l1 = [], l2 = [0]
输出:[0]
解题思路
- 判断如果两个链表其中有一个为空,则返回另一个链表
- 从两个链表的第一个值进行比较,如果第一个链表的第一个值小于第二个链表的第一个值,则更新mergelist的值为第一个链表
- 递归更新mergelist->next
代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
if (list1 == NULL) {
return list2;
}
if (list2 == NULL) {
return list1;
}
struct ListNode* mergedList;
if (list1->val <= list2->val) {
mergedList = list1;
mergedList->next = mergeTwoLists(list1->next, list2);
} else if(list1->val > list2->val) {
mergedList = list2;
mergedList->next = mergeTwoLists(list1, list2->next);
}
return mergedList;
}
Leecode-14-最长公共前缀
题目
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例
示例1
输入:strs = [“flower”,“flow”,“flight”]
输出:“fl”
示例2
输入:strs = [“dog”,“racecar”,“car”]
输出:“”
解释:输入不存在公共前缀。
解题思路
纵向比较,先判断每一行的第一个元素是否相等,若相等则指针指向先一个元素,不相等则将这个字符赋’\0’,返回
代码实现
char* longestCommonPrefix(char** strs, int strsSize) {
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';
break;
}
}
}
return strs[0];
}
Leecode-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”]]
解题思路
对于每个回溯节点,以当前位置offset开始进行操作,向后依次进行遍历:
- 如果某个位置达成了回文子串的要求,那么就记录当前位置并以此为基础进行下一层的递推,完毕后进行回溯,消除当前分支操作的影响为下一个位置的递推做好准备;
- 如果当前位置不是就不进行操作而是继续进行后续的遍历直至到达字符串末尾;
- 如果当前位置到达了字符串的结束符位置,那么就到达了递推边界,则将Path中的位置记录转化为字符串存储于结果数组Result中并返回;
作者:随心
链接:https://leetcode.cn/problems/M99OJA/solutions/2539472/fen-ge-hui-wen-chuan-hui-su-suan-fa-si-l-3bgj/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
代码实现
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
bool isPalindrome(char* s, int l, int r){
while(l <= r){
if(s[l] != s[r]){
return false;
}
l++;
r--;
}
return true;
}
char* S = NULL;
int* RSIZE = NULL;
int RCOLSIZES[32768];
int LEN = 0;
int* Path = NULL;
int Path_Index = 0;
char** Result[32768];
void Duplicate(char*** des){
*des = (char**)malloc(sizeof(char*) * Path_Index);
for(int i = 0; i < Path_Index; i++){
int sublen = Path[i] - (i ? Path[i - 1] : -1);
int start = i ? (Path[i - 1] + 1) : 0;
(*des)[i] = (char*)malloc(sizeof(char) * (sublen + 1));
for(int j = 0; j < sublen; j++){
(*des)[i][j] = S[start + j];
}
(*des)[i][sublen] = '\0';
}
}
void Back_Track(int offset){
if(offset == LEN){
Duplicate(Result + *RSIZE);
RCOLSIZES[*RSIZE] = Path_Index;
(*RSIZE)++;
return;
}
for(int i = offset; i < LEN; i++){
if(isPalindrome(S, offset, i)){
Path[Path_Index] = i;
Path_Index++;
Back_Track(i + 1);
Path_Index--;
}
else{
continue;
}
}
}
char*** partition(char* s, int* returnSize, int** returnColumnSizes){
S = s;
RSIZE = returnSize;
*returnColumnSizes = RCOLSIZES;
*RSIZE = 0;
LEN = strlen(s);
Path = (int*)malloc(sizeof(int) * LEN);
Path_Index = 0;
Back_Track(0);
return Result;
}