移动应用开发实验室第三次纳新面试题分析

本文详细解读了五道编程题目,涉及括号匹配算法、字符串反转影响的键盘输入、三数之和问题、合并有序链表和查找最长公共前缀。展示了如何使用数据结构和字符串处理技巧解决问题。
摘要由CSDN通过智能技术生成

第一题.20有效的括号

题目描述:

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

有效字符串需满足:

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

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • 1 <= s.length <= 104
  • s 仅由括号 '()[]{}' 组成

代码实现:

 

char pairs(char a)
{
    if(a==')')
    {
        return '(';
    }
    else if(a==']')
    {
        return '[';
    }
    else if(a=='}')
    {
        return '{';
    }
    return 0;
}
bool isValid(char* s) {
    int l=strlen(s);
    if(l%2!=0)
    {
        return false;
    }
    char arr[l];
    int t=0;
    for(int i=0;i<l;i++)
    {
        char c=pairs(s[i]);
        if(c)
        {
            if(t==0||c!=arr[t-1])
            {
                return false;
            }
            t--;
        }
        else
        {
            arr[t++]=s[i];
        }
    }
    return t==0;
}

主要方法:

1.建立哈希表

2.利用栈的算法思想

解题思路:

1.建立哈希表,实现当输入右括号时返回对应的左括号。

2.判断传入的数组长度是否为奇数,如果为奇数则直接返回false.

3.单独创建一个数组arr,当字符数组当前字符为左括号时将当前字符存入arr,也称进入栈中,接下来,进行下一个字符判断,若下一字符经过哈希表的转换可以与arr中最近的一个字符配对,则将栈中与之配对的字符出栈。总之,栈中的字符都是未经过配对的左括号。

4.在循环中,当当前字符为右括号时,经过哈希表的转换使之与栈中最近的一个字符进行比较,若相等则表示配对,并使栈中最近的一个字符出栈,若不相等则直接返回false 

5.结束循环后,判断此时栈中是否还有字符,有则返回false,没有则返回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'

代码实现: 

char* finalString(char* s) {
    int i,j,n,t,m=0,x;
	x=strlen(s);
	for(i=0;i<x;i++)
	{
		if(s[i]=='i')
		{
			t=m-1;
			for(j=0;j<t;j++,t--)
			{
				char y=s[j];
				s[j]=s[t];
				s[t]=y;
			}
		}
		else
		{
			s[m]=s[i];
			m++;
		}	
	}
	s[m]='\0';
	return s;
}

解题思路:

 首先求出字符串的长度,以便得出for循环终止条件,在循环中,判断当前字符是否为i,为i时,反转之前的字符,否则当前字符不变,当循环完成时给字符串当前位置赋值'\0',表示字符串结束,返回字符串s。

第三题.15三数之和

题目描述:

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

代码实现: 

// 使用 qsort函数时的比较函数
int comp(const void* a, const void* b)
{
    return *(int*)a - *(int*)b;
}
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) { 
//从小打到排序
	if (numsSize == 0) return 0;
	qsort(nums,numsSize,sizeof(int),comp);
	int row = 0;
	int **ret = (int **)malloc(sizeof(int *) * (numsSize + 1) * 6);
	int left = 0,right = numsSize - 1;
	int target  = 0;
	*returnColumnSizes = malloc(sizeof(int) * (numsSize + 1) * 6);
	while(left + 1 < right) {
	int i = left + 1;
	int j = right;
	target = 0 - nums[left];
	while (i < j) {
        	if(nums[i] + nums[j] < target){
        		i++;
        	} else if (nums[i] + nums[j] > target){
        		j--;
        	} else {
	            ret[row] = (int *)malloc(sizeof(int) * 3);
	            ret[row][0] = nums[left];
	            ret[row][1] = nums[i];
	            ret[row][2] = nums[j];
	            (*returnColumnSizes)[row] = 3;
	            row ++;
	            while(nums[i] == nums[++i] && i < j) {};
	            while(nums[j] == nums[--j] && i < j) {};
        	}
 	}
    	while(nums[left] == nums[++left] && left + 1 < right) {};

	}
	retun ret;
}

主要思想: 排序+双指针

解题思路: 首先对数组进行排序,然后创建一个二维数组,以便储存符合条件的三数,固定第一个值,将第一个值之后的第一个数固设为左指针,将数组内的最后一个值设定为右指针,判断此时三个数是否为零,若为0,则将此时三个数存入创建的二维数组中,若不为0,则进一步判断三数加起来比0大还是比0小,若大于0,移动右指针,小于0,移动左指针。

第四题.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 均按 非递减顺序 排列

代码实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    struct ListNode *head,*r,*p,*q;
    p=list1;
    q=list2;
    head=(struct ListNode*)malloc(sizeof(struct ListNode));
    r=head;
    while(p&&q)
    {
        if(p->val<=q->val)
        {
             r->next=p;
             p=p->next;
        }
        else
        {
            r->next=q;
            q=q->next;
        }
        r=r->next;
    }
    if(p==NULL)
    {
        r->next=q;
    }
    else if(q==NULL)
    {
        r->next=p;
    }
    return head->next;
}

解题思路:

1.首先创建一个新的头结点head,创建r与head相等,当两条链表都不为空时进入循环,比较两条链表的头结点中的数据大小,令r指向较小数据的结点,并将较小数据结点向后移动一位,同时,r也向后移动一位(r=r->next)

2.当其中一条链表为空时,跳出循环,使此时r指向不为空的另一条指针。

3.返回已合并的新链表的头结点。

第五题.14最长公共前缀

题目描述:

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""

示例 1:

输入:strs = ["flower","flow","flight"]
输出:"fl"

示例 2:

输入:strs = ["dog","racecar","car"]
输出:""
解释:输入不存在公共前缀。

提示:

  • 1 <= strs.length <= 200
  • 0 <= strs[i].length <= 200
  • strs[i] 仅由小写英文字母组成

代码实现: 

char* longestCommonPrefix(char** strs, int strsSize) {
    for(int i=0;i<strlen(strs[0]);i++)
    {
        for(int j=1;j<strsSize;j++)
        {
            
            if(strs[j][i]!=strs[0][i])
            {
                strs[0][i]='\0';
                return strs[0];
            }
        }
    }
    return strs[0];
}

解题思路:

将第一个字符串当作模板,将其他字符串与第一个字符串位置相同的字符进行比较,若不相等则结束循环,并将第一个字符串当前字符位置赋值'\0',表示字符串结束,并返回第一个字符串作为最长公共前缀。

 

  • 34
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值