wwww三面题解wwww

23大一下Web三面题解

20.有效的括号

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

示例 1:

输入:s = "()"
输出:true

示例 2:

输入:s = "()[]{}"
输出:true

示例 3:

输入:s = "(]"
输出:false

提示:

  • 1 <= s.length <= 104

  • s 仅由括号 '()[]{}' 组成

    bool isValid(char* s) {
        int l = strlen(s);
        int p=0,i=0;
        char arr[l];	//栈数组
        for(i=0;i<l;i++){
            if(s[i]=='('||s[i]=='['||s[i]=='{'){	//若是左括号就入栈
                arr[p++]=s[i];
                        
            }else{	//右括号的情况
                if(p<=0){	//栈空,自然无法配对,直接返回false
                    return false;
                }
                if(s[i]==')'){
                    if(arr[p-1]!='('){	//不匹配,返回假
                        return false;
                    }else{
                        p--;	//匹配,将栈指针减一实现出栈
                    }
                }else if(s[i]==']'){
                    if(arr[p-1]!='['){
                        return false;
                    }else{
                        p--;
                    }
                }else{
                    if(arr[p-1]!='{'){
                        return false;
                    }else{
                        p--;
                    }
                }
            }
        }
        if(p>0){
            return false;	//匹配到最后栈一定为空,否则就为假
        }
        return true;
    }
    

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'

    void reverse(char* s,int i,int j){	//反转函数
        while(i<j){
            char temp=s[i];
            s[i++]=s[j];
            s[j--]=temp;
        }
    }
            
    char* finalString(char* s) {
        int i=0;
        int l=strlen(s);
        for(i=0;i<l;i++){	//正常遍历,遇到i就将前面的字符反转
            if(s[i]=='i'){
                reverse(s,0,i-1);
            }
        }
        int j=0;
        for(i=0;i<l;i++){	//再遍历一次,将字符串里面的i去掉
            if(s[i]!='i'){
                s[j++]=s[i];
            }
        }
        s[j]='\0';
        return s;
    }
    

15.三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != 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

/**
 * 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** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) {
    int i,j;
    int **ans=(int**)malloc(sizeof(int*)*18000);
    int anstop=0;
    for(i=0;i<numsSize-1;i++){	//冒泡排序,将数组从小到大来排列
        for(j=0;j<numsSize-i-1;j++){
            if(nums[j]>nums[j+1]){
                int temp =nums[j];
                nums[j]=nums[j+1];
                nums[j+1]=temp;
            }
        }
    }
    for(i=0;i<numsSize-2;i++){
        if(nums[i]>0){	//如果第一个数就大于零了,就没必要继续进行比较了,直接返回答案
            break;
        }
        if(i>0&&nums[i]==nums[i-1]){	//这一段代码的作用是去重,这里和前一个数比较是为了去重的同时不漏掉答案
            continue;
        }
        int left=i+1;
        int right=numsSize-1;	//在剩下的数的两端,往里面收,寻找合适的三元组
        while(left<right){
            int sum=nums[i]+nums[left]+nums[right];
            if(sum>0){	//若是大于零,则要将三元组的值减小,就是将right往左移动
                right--;
            }else if(sum<0){	//小于零则left往右移动
                left++;
            }else{
                int *arr=(int*)malloc(sizeof(int)*3);	//找到了合适的三元组,分配内存,再存入二维数组里面
                arr[0]=nums[i];
                arr[1]=nums[left];
                arr[2]=nums[right];
                ans[anstop++]=arr;
                while(right>left&&nums[right]==nums[right-1]){	//去重
                    right--;
                }
                while(left<right&&nums[left]==nums[left+1]){
                    left++;
                }
                left++;
                right--;
            }
        }
    }
    *returnSize=anstop;
    *returnColumnSizes=(int*)malloc(sizeof(int)*anstop);
    int z;
    for(z=0;z<anstop;z++){
        (*returnColumnSizes)[z]=3;	//设置返回数组的列数
    }
    return ans;
}

21.合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例 1:

img

输入: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

  • l1l2 均按 非递减顺序 排列

    struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
        struct ListNode* newhead = (struct ListNode*)malloc(sizeof(struct ListNode));
        newhead->next = NULL;
        struct ListNode* cur = newhead;
                
        while(list1 != NULL || list2 != NULL){
            if(list1 == NULL){
                cur->next = list2;
                break;
            }
            if(list2 == NULL){
                cur->next = list1;
                break;
            }
            if(list1->val < list2->val){
                cur->next = list1;
                list1 = list1->next;
            }else{
                cur->next = list2;
                list2 = list2->next;
            }
            cur = cur->next;
        }
                
        return newhead->next;
    }
            
    

179.最大数

给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。

**注意:**输出结果可能非常大,所以你需要返回一个字符串而不是整数。

示例 1:

输入:nums = [10,2]
输出:"210"

示例 2:

输入:nums = [3,30,34,5,9]
输出:"9534330"

提示:

  • 1 <= nums.length <= 100

  • 0 <= nums[i] <= 109

    //本题的关键就是开始的排序,从结果出发的话,数组里面每个数的位置都是固定的,这样才有了组合起来的最大值,通过冒泡排序,可以比较两个数的两种组合实现值的大小,不断把组合起来数值小的那个数往后排,这些往后移动的数都是在每一次循环中最适合放在末位的数,最后得到的排序就是题目要求的排序。
    void sort(int* num,int numsSize){
        for(int i=0;i<numsSize-1;i++){
            for(int j=0;j<numsSize-i-1;j++){
                char s1[100000];
                char s2[100000];
                sprintf(s1,"%d%d",num[j],num[j+1]);
                sprintf(s2,"%d%d",num[j+1],num[j]);
                if(strcmp(s2,s1)>0){
                    int temp=num[j];
                    num[j]=num[j+1];
                    num[j+1]=temp;
                }
            }
        }
    }
          
    char *largestNumber(int* nums, int numsSize){
        sort(nums,numsSize);
        if(nums[0]==0){	//如果第一个数为0的话,意味着后面的数都是0
            return "0";
        }
        char* ans=(char*)malloc(sizeof(char)*10000000);	//为答案数组分配内存
        memset(ans,'\0',10000000);	//因为一开始分配了很多内存,然后答案也是作为字符返回,答案的长度不太好确定,就全部设置为'\0'
        for(int i=0;i<numsSize;i++){	//这里是将排好序的数拼接起来
            char s1[10000];
            sprintf(s1,"%d",nums[i]);
            strcat(ans,s1);
        }
        return ans;
    }
    
    
    

LCR 086. 分割回文串

给定一个字符串 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 仅由小写英文字母组成

    对于这道题目,关键点是处理好分割点,然后和答案数组的处理,因为题目要求的是将字串分割成每一个都是回文串

    char** path;
     int pathtop;
     char*** ans;
     int anstop;
     int* anssize;
    void copy() {	//避免函数复杂,这里单独写一个函数将path数组里面记录的组合放入安安数组
        char** temp = (char**)malloc(sizeof(char*) * pathtop);
        int i = 0;
        for(i = 0; i < pathtop; i++) {
            temp[i] = path[i];
        }
        ans[anstop] = temp;
        anssize[anstop++] = pathtop;
    }
    
    char* cutstring(char* str,int startindex, int endindex) {	//这是将原数组分割,将分割后的字符串拿出来
        char* temp = (char*)malloc(sizeof(char) * (endindex - startindex + 2));
        int i;
        int index = 0;
        for(i = startindex; i <= endindex; i++) {
            temp[index++] = str[i];
        }
        temp[index] = '\0';
        return temp;
    }
    
    bool ishui(char* str, int startindex, int endindex) {	//判断是否时回文串
        while(startindex <= endindex) {
            if(str[startindex++] != str[endindex--]) {
                return 0;
            }
        }
        return 1;
    }
    
    void backtracking(char* str,int strlen, int startindex) {
        if(startindex >= strlen) {	//递归结束条件,记录过的符合要求的子串放入答案数组里面
            copy();
            return;
        }
    
        int i;
        for(i = startindex; i < strlen; i++) {	//从当前数组开始向后遍历
            if(ishui(str, startindex, i)) {	//如果当前字符串符合要求,则记录,然后进入下一层递归
                path[pathtop++] = cutstring(str, startindex, i);
            }else {	//要是不符合回文串,后面也就没必要遍历了
                continue;
            }
            backtracking(str, strlen, i + 1);
            pathtop--;	//回溯,将前一个记录的字符串弹出
        }
    }
    
    char*** partition(char* s, int* returnSize, int** returnColumnSizes){
        int l = strlen(s);
        path = (char**)malloc(sizeof(char*) * l);
        ans = (char***)malloc(sizeof(char**) * 40000);
        anssize = (int*)malloc(sizeof(int) * 40000);
        anstop = pathtop = 0;
    
        backtracking(s, l, 0);
        *returnSize = anstop;
        *returnColumnSizes = (int*)malloc(sizeof(int) * anstop);
        int i;
        for(i = 0; i < anstop; i++) {
            (*returnColumnSizes)[i] = anssize[i];
        }
        return ans;
    }
    

217.存在重复元素

给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false

示例 1:

输入:nums = [1,2,3,1]
输出:true

示例 2:

输入:nums = [1,2,3,4]
输出:false

示例 3:

输入:nums = [1,1,1,3,3,4,3,2,4,2]
输出:true

提示:

  • 1 <= nums.length <= 105

  • -109 <= nums[i] <= 109

    //这道题目排序后再判断相邻的数是否重复,但是效率不高的排序会超时,这里用系统自己带的快排
    int compare(const void *a, const void *b) {
    	return (*(int*)a - *(int*)b);
    }
    bool containsDuplicate(int* nums, int numsSize) {
        qsort(nums,numsSize,sizeof(int),compare);
        for(int i=0;i<numsSize-1;i++){
            if(nums[i]==nums[i+1]){
                return true;
            }
        }
        return false;
    }
    

58. 最后一个单词的长度

给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。

单词 是指仅由字母组成、不包含任何空格字符的最大

子字符串

示例 1:

输入:s = "Hello World"
输出:5
解释:最后一个单词是“World”,长度为5。

示例 2:

输入:s = "   fly me   to   the moon  "
输出:4
解释:最后一个单词是“moon”,长度为4。

示例 3:

输入:s = "luffy is still joyboy"
输出:6
解释:最后一个单词是长度为6的“joyboy”。

提示:

  • 1 <= s.length <= 104
  • s 仅有英文字母和空格 ' ' 组成
  • s 中至少存在一个单词
//要计算最后一个单词长度,直接从字符串末尾开始往前数,再添加合适的判断就可求解
int lengthOfLastWord(char* s) {
    int l=strlen(s);
    int ans=0;
    for(int i=l-1;i>=0;i--){	//有两种遇到空格的情况,一种是末尾有空格,另一种是结束时遇到的空格
        if(s[i]==' '&&ans>0){	//这里是处理结束时的空格,如果已经遇到过单词,再遇到空格,则说明结束了
            break;
        }
        if(s[i]!=' '){	//计算答案数
            ans++;
        }
        //末尾空格不用多加处理
    }
    return ans;
}

出:4

解释:最后一个单词是“moon”,长度为4。


**示例 3:**

输入:s = “luffy is still joyboy”
输出:6
解释:最后一个单词是长度为6的“joyboy”。


 

**提示:**

- `1 <= s.length <= 104`
- `s` 仅有英文字母和空格 `' '` 组成
- `s` 中至少存在一个单词
//要计算最后一个单词长度,直接从字符串末尾开始往前数,再添加合适的判断就可求解
int lengthOfLastWord(char* s) {
    int l=strlen(s);
    int ans=0;
    for(int i=l-1;i>=0;i--){	//有两种遇到空格的情况,一种是末尾有空格,另一种是结束时遇到的空格
        if(s[i]==' '&&ans>0){	//这里是处理结束时的空格,如果已经遇到过单词,再遇到空格,则说明结束了
            break;
        }
        if(s[i]!=' '){	//计算答案数
            ans++;
        }
        //末尾空格不用多加处理
    }
    return ans;
}

  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值