写在前面:本人最近在找暑期实习,面了字节发现自己啥都不会,所以想通过这篇博客记录一下自己每天一题算法题的过程(不鸽),代码均为手敲,大部分只是求过(也可能只是过了样例),低性能代码模范了。也欢迎大家指出错误,并一起做算法题。
目录
1.大整数加法
2.两数相加 - 简单
3.无重复字符的最长子串(滑动窗口) - 中等
4.盛最多水的容器(双指针遍历)- 中等
字节面试的算法题,我当时怎么这个都做不出...
【题目描述】
求两个不超过200位的非负整数的和。【输入】
有两行,每行是一个不超过200位的非负整数,可能有多余的前导0。【输出】
一行,即相加后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。【输入样例】
22222222222222222222
33333333333333333333【输出样例】
55555555555555555555
手写代码:
#include
#include
using namespace std;
int main(){
string add1, add2,add_max;
char add_min[202],sum[202];
for(int i = 0; i < 202; i++)
{
add_min[i] = sum[i] = '0';
}
cin >> add1 >> add2;
int length1 = add1.length();
int length2 = add2.length();
int maxlength = max(length1,length2);
int minlength = min(length1,length2);
if(length2 == maxlength)
{
string test = add1;
add1 = add2;
add2 = test;
}
add_max = add1;
for(int i = maxlength - minlength; i < maxlength; i++)
add_min[i] = add2[i-(maxlength - minlength)];
for(int i = maxlength - 1; i >= 0; i--)
{
int temp = add_min[i] + add_max[i] - '0' * 2;
if(temp >= 10) {
sum[i] = temp - 10 + '0';
if(i==0)
{
for(int j = maxlength; j > 0; j--)
{
sum[j] = sum[j - 1];
}
sum[0] = '1';
maxlength++;
}
else
add_min[i-1] += 1;}
else sum[i] = temp + '0';
}
for(int i = 0; i < maxlength; i++)
cout << sum[i];
cout << endl;
}
原题:1. 两数之和 - 力扣(LeetCode)
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
暴力法如下:
知识:
1.size()为数组长度获取。
class Solution {
public:
vector twoSum(vector& nums, int target) {
int i , j;
for(i = 0; i < nums.size() - 1; i++)
{
for(j = i + 1; j < nums.size() ; j++)
{
if(nums[i] + nums[j] == target)
{
return {i , j};
}
}
}
return {i , j};
}
};
该方法简单但是时间复杂度为 O(n^2^)。空间复杂度为 O(1);运行速度慢且内存空间消耗大
原题:3. 无重复字符的最长子串 - 力扣(LeetCode)
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
暴力法会时间超限,就不放了,这里使用滑动窗口,原理如下:
代码如下:
class Solution{
public:
int lengthOfLongestSubstring(string s)
{
int left(0),right(0),maxlength(0),templength(0);
int length = s.length();
while(right < length)
{
for(int j = left; j < right; j++)
{
if(s[j] == s[right])
{
templength = right - left;
if(templength > maxlength) maxlength = templength;
left = j + 1;
templength = 0;
break;
}
}
right++;
templength = right - left;
}
return max(templength,maxlength);
}
};
原题:11. 盛最多水的容器 - 力扣(LeetCode)
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
暴力法仍然会超限(我怎么什么题目都喜欢用暴力法,果然简单的才是最好的),在这里使用双指针遍历,但好像时间还有待优化,原理如下:
核心:从左右两边按短板往中间收缩。
class Solution {
public:
int maxArea(vector& height) {
int size = height.size(),num = size - 1;
int left(0),right(size-1);
int max_water = min(height[left],height[right]) * (right-left);
for(int i = 0; i < num; i++)
{
if(height[left] == min(height[left],height[right]))
{
left++;
int temp_water = min(height[left],height[right]) * (right-left);
max_water = max(max_water,temp_water);
// cout << "left " << max_water << endl;
continue;
}
if(height[right] == min(height[left],height[right]))
{
right--;
int temp_water = min(height[left],height[right]) * (right-left);
max_water = max(max_water,temp_water);
// cout << "right " << max_water << endl;
continue;
}
}
return max_water;
}
};