目录
LeetCode 第41题:缺失的第一个正数
LeetCode 第42题:接雨水
LeetCode 第43题:字符串相乘
LeetCode 第41题:缺失的第一个正数
题目描述:
给你一个未排序的整数数组
nums
,请你找出其中没有出现的最小的正整数。请你实现时间复杂度为
O(n)
并且只使用常数级别额外空间的解决方案。难度:困难
题目链接:41. 缺失的第一个正数 - 力扣(LeetCode)
示例1:
输入:nums = [1,2,0] 输出:3 解释:数字 1 和 2 都出现了,所以最小的缺失正整数是 3
示例2:
输入:nums = [3,4,-1,1] 输出:2 解释:1 出现了,但 2 没有出现,所以最小的缺失正整数是 2
示例3:
输入:nums = [7,8,9,11,12] 输出:1 解释:最小的正整数 1 没有出现,所以答案是 1
提示:
1 <= nums.length <= 5 * 10^5 -2^31 <= nums[i] <= 2^31 - 1
解题思路:
方法一:原地哈希法
- 数组长度为n,那么缺失的第一个正整数一定在【1,n+1】范围内。
- 可以将数字k放到数组的第k-1个位置上
- 遍历完成后,第一个不在对应位置上的数字的下标加1就是答案
int firstMissingPositive(int* nums,int numsSize) {//将数组当中的非正数改为正数for(int i=0;i<numsSize;i++){if(nums[i]<=0) nums[i] = numsSize+1;}//从1开始,如果存在数字将对应位置的数字标记为负数for(int i=0;i<numsSize;i++){int num = abs(nums[i]);if(num<=numsSize) nums[num-1] = -abs(nums[num-1]);}//返回第一个没有出现的整数,对应于数组的第一个正数的位置+1for(int i=0;i<numsSize;i++){if(nums[i]>0) return i+1;}//如果上述for循环没有return,则说明对应位置都有正整数,则返回下一个位置对应的正整数return numsSize+1; }
方法二:置换法
int firstMissingPositive(int* nums,int numsSize) {for(int i=0;i<numsSize;i++){//当nums[i]在数组索引范围内,并且数字对应的索引-1的位置没有出现该数字的时候//交换两者的位置while(nums[i]>0 && nums[i]<=numsSize && nums[nums[i]-1]!=nums[i]){int t = nums[nums[i]-1];nums[nums[i]-1] = nums[i];nums[i]=t;}for(int i=0;i<numsSize;i++){if(nums[i]!=i+1) return i+1;}return numsSize+1;} }
LeetCode 第42题:接雨水
题目描述:
给定
n
个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。难度:困难
题目链接:42. 接雨水 - 力扣(LeetCode)
示例1:
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
示例2:
输入:height = [4,2,0,3,2,5] 输出:9
提示:
n == height.length 1 <= n <= 2 * 10^4 0 <= height[i] <= 10^5
解题思路:双指针
- 使用左右指针分别指向数组两端,每个位置能接的雨水量=min(左侧最大高度,右侧最大高度)-当前高度
- 每次移动较小的那一侧的指针
- 累加当前位置能接的雨水量
int Trap(int* height,int numsSize) {if(height==null || numsSize<3) return 0;int left = 0,right = numsSize-1;int leftMax = 0,rightMax = 0;int result = 0;while(left<right){//更新左右两侧的最大高度leftMax = fmax(leftMax,height[left]);rightMax = fmax(rightMax,height[right]);//移动较小的一侧if(leftMax<rightMax) {result = result+leftMax - height[left];left++;}else{result = result+rightMax - height[right];right--;}}return result; }
LeetCode 第43题:字符串相乘
题目描述:
给定两个以字符串形式表示的非负整数
num1
和num2
,返回num1
和num2
的乘积,它们的乘积也表示为字符串形式。注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。
难度:中等
题目链接:43. 字符串相乘 - 力扣(LeetCode)
示例1:
输入:num1 = "2", num2 = "3" 输出:"6"
示例2:
输入:num1 = "123", num2 = "456" 输出:"56088"
提示:
1 <= num1.length, num2.length <= 200 num1 和 num2 只能由数字组成 num1 和 num2 都不包含任何前导零,除了数字0本身
解题思路:竖乘法
- 两个长度分别为m和n的数字相乘,结果最多有m+n位
- 从个位开始,逐位相乘并累加到对应位置
- 处理进位
- 去除前导零,转换为字符串
string Multiply(char* num1,char* num2) {if(num1==“0” || num2=="0") return "0";int m = strlen(num1),n=strlen(num2);char* result = (char*)malloc(m+n+1);for(int i=m-1;i>=0;i--){for(int j=n-1;j>=0;j--){int mul = (num1[i]-'0')*(num2[j]-'0')//定义高位和低位int p1=i+j,p2=i+j+1;//叠加到结果数组int sum = mul+result[p2];result[p2] = sum %10;result[p1] = result[p1]+sum/10;}}//在result数组中找到第一个不为0的数字,并开始输出bool flag=true;char* str = (char*)malloc(m+n+1);for(int k=m+n;k>=0;k--){if(result[k]==0 && flag==true) continue;flag =false;str[k]=result[k];}return strlen(str)==0 ? "0" : str; }