LeetCode新手村

2024-02-12 15:20
文章标签 leetcode 新手村

本文主要是介绍LeetCode新手村,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

博友们,如果觉得看文字不好理解,可以看我的讲解视频:讲解视频

2022/6/6

1480.一维数组的动态和

给你一个数组 nums 。数组「动态和」的计算公式为:runningSum[i] = sum(nums[0]…nums[i]) 。
请返回 nums 的动态和。

示例 1:

输入:nums = [1,2,3,4]
输出:[1,3,6,10]
解释:动态和计算过程为 [1, 1+2, 1+2+3, 1+2+3+4] 。

示例 2:

输入:nums = [1,1,1,1,1]
输出:[1,2,3,4,5]
解释:动态和计算过程为 [1, 1+1, 1+1+1, 1+1+1+1, 1+1+1+1+1] 。

示例 3:

输入:nums = [3,1,2,10,1]
输出:[3,4,6,16,17]

解题思路为:

初始化一个新的数组为sum,数组的长度即为输入数组的长度,
由题可知
sums[0]=nums[0];
sums[i]=nums[i]+sums[i-1];
使用for循环遍历进行计算,计算次数为nums的长度,注意从i=1进行循环。

class Solution {
public:vector<int> runningSum(vector<int>& nums) {vector<int> sum(nums.size());sum[0]=nums[0];for(int i=1;i<nums.size();i++){sum[i]=sum[i-1]+nums[i];}return sum;
}};

2.c++的for auto用法
for(auto item:list)进行遍历数组中的全部元素,不改变数组元素大小,
for(auto &item:list)改变item的值就改变了数组元素的值。
3.js的for of用法
for(let item of list)进行遍历数组list的每一个元素值。
4.charCodeAt()
用于返回一个字符的unicode值

383. 赎金信

题目:
给你两个字符串:ransomNote 和 magazine ,判断ransomNote 能不能由 magazine 里面的字符构成。如果可以,返回 true ;否则返回 false 。magazine 中的每个字符只能在 ransomNote 中使用一次。

示例 1:

输入:ransomNote = “a”, magazine = “b”
输出:false

示例 2:

输入:ransomNote = “aa”, magazine = “ab”
输出:false

示例 3:

输入:ransomNote = “aa”, magazine = “aab”
输出:true

解题思路为:

1.首先如果magazine的字符的个数小于ransomNote的个数,则返回为false。

2.统计magazine中每个字母出现的个数,统计ransomNote中每个字母的个数,比较两个集合中相同字母出现个数的比较,例如,若magazine中a的个数小于ransomNote中a的个数,则返回false。

c代码

class Solution {
public:bool canConstruct(string ransomNote, string magazine) {
vector<int> num(26);
if(ransomNote.size()>magazine.size())
return false;//对magazine出现的26个字母的个数进行统计,分别统计每个字母出现的个数
for(auto item:magazine){   num[item-'a']++;
} 
//对ransomeNote出现的的字母得个数进行统计,对magazine中每个字母进行相减,
//若值小于为0,则说明ransomNote中字母个数多于magazine中字母个数,则返回false.
for(auto item:ransomNote){     num[item-'a']--;if(num[item-'a']<0)return false;
}
return true;}
};

javascript

/*** @param {string} ransomNote* @param {string} magazine* @return {boolean}*/
var canConstruct = function(ransomNote, magazine) {
let num=new Array(26).fill(0);
if(ransomNote.length>magazine.length)
return false;
for(let item of magazine)
{num[item.charCodeAt()-'a'.charCodeAt()]++;
}
for(let item of ransomNote){num[item.charCodeAt()-'a'.charCodeAt()]--;if(num[item.charCodeAt()-'a'.charCodeAt()]<0){return false;}}
return true;
};

2022/6/8

c++
push_back和emplace_back都是在容器末尾添加一个新元素进去。
to_string()将整数i转换为字符串表现形式i

412. Fizz Buzz

给你一个整数 n ,找出从 1 到 n 各个整数的 Fizz Buzz 表示,并用字符串数组 answer(下标从 1 开始)返回结果,其中:

answer[i] == “FizzBuzz” 如果 i 同时是 3 和 5 的倍数。
answer[i] == “Fizz” 如果 i 是 3 的倍数。
answer[i] == “Buzz” 如果 i 是 5 的倍数。
answer[i] == i (以字符串形式)如果上述条件全不满足。

示例 1:

输入:n = 3
输出:[“1”,“2”,“Fizz”]

示例 2:

输入:n = 5
输出:[“1”,“2”,“Fizz”,“4”,“Buzz”]

示例 3:

输入:n = 15
输出:[“1”,“2”,“Fizz”,“4”,“Buzz”,“Fizz”,“7”,“8”,“Fizz”,“Buzz”,“11”,“Fizz”,“13”,“14”,“FizzBuzz”]

解题思路:

1.就是先创建一个字符数组vector answer,给定整数n进行for循环,创建一个字符串string ctn,if(n%3==0)ctn+="Fizz";if(n%5==0) ctn+="Buzz";

如果ctn的大小为0,则说明应该添加整数i,将整数变为字符格式,使用to_string()进行转换。

class Solution {
public:vector<string> fizzBuzz(int n) {vector<string> answer;for(int i=1;i<=n;i++){string curr;if(i%3==0)curr+="Fizz";if(i%5==0)curr+="Buzz";if(curr.size()==0)curr+=to_string(i);answer.emplace_back(curr);}return answer;}
};

876. 链表的中间结点

给定一个头结点为 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

示例 1:

输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.

示例 2:

输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。

解题思路:数组法

首先创建一个数组指向头节点,将链表中的每一个元素放入到数组中,得到数组的中部元素,也就是数组长度/2,就得到了链表中的中间元素.

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* middleNode(ListNode* head) {vector<ListNode *> cur={head};while(cur.back()->next!=NULL){cur.push_back(cur.back()->next);}return cur[cur.size()/2];}
};

2022/6/10

1342.将数字变成 0 的操作次数

将数字变成 0 的操作次数给你一个非负整数 num ,请你返回将它变成 0 所需要的步数。 如果当前数字是偶数,你需要把它除以 2 ;否则,减去 1 。

示例 1:

输入:num = 14
输出:6
解释:
步骤 1) 14 是偶数,除以 2 得到 7 。
步骤 2) 7 是奇数,减 1 得到 6 。
步骤 3) 6 是偶数,除以 2 得到 3 。
步骤 4) 3 是奇数,减 1 得到 2 。
步骤 5) 2 是偶数,除以 2 得到 1 。
步骤 6) 1 是奇数,减 1 得到 0 。

示例 2:

输入:num = 8
输出:4
解释:
步骤 1) 8 是偶数,除以 2 得到 4 。
步骤 2) 4 是偶数,除以 2 得到 2 。
步骤 3) 2 是偶数,除以 2 得到 1 。
步骤 4) 1 是奇数,减 1 得到 0 。

示例 3:

输入:num = 123
输出:12

解题思路:

使用for循环,当num的值小于0时跳出循环,当num%2==0时,num=num/2,当num%2==1时,num-=num。

class Solution {
public:int numberOfSteps(int num) {
int ctn=0;
while(num>0){
if(num%2==0)
num=num/2;
else
num-=1;
ctn++;}
return ctn;}
};

1672. 最富有客户的资产总量

给你一个 m x n 的整数网格 accounts ,其中 accounts[i][j] 是第 i​​​​​​​​​​​​ 位客户在第 j 家银行托管的资产数量。返回最富有客户所拥有的 资产总量 。

客户的 资产总量 就是他们在各家银行托管的资产数量之和。最富有客户就是 资产总量 最大的客户。

示例 1:

输入:accounts = [[1,2,3],[3,2,1]]
输出:6
解释:
第 1 位客户的资产总量 = 1 + 2 + 3 = 6
第 2 位客户的资产总量 = 3 + 2 + 1 = 6
两位客户都是最富有的,资产总量都是 6 ,所以返回 6 。

示例 2:

输入:accounts = [[1,5],[7,3],[3,5]]
输出:10
解释:
第 1 位客户的资产总量 = 6
第 2 位客户的资产总量 = 10
第 3 位客户的资产总量 = 8
第 2 位客户是最富有的,资产总量是 10

示例 3:

输入:accounts = [[2,8,7],[7,1,3],[1,9,5]]
输出:17

解题思路:

首先使用for循环遍历每行的元素,将每行的元素累加起来后,通过比较大小来确定最大值。

1.累加求和

int sum = accumulate(vec.begin() , vec.end() , 42);
accumulate带有三个形参:头两个形参指定要累加的元素范围,第三个形参则是累加的初值。

accumulate函数将它的一个内部变量设置为指定的初始值,然后在此初值上累加输入范围内所有元素的值。accumulate算法返回累加的结果,其返回类型就是其第三个实参的类型。

class Solution {
public:int maximumWealth(vector<vector<int>>& accounts) {int maxWealth=0;for(auto item:accounts){maxWealth=max(maxWealth,accumulate(item.begin(),item.end(),0));}return maxWealth;}
};

26. 删除有序数组中的重复项

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

将最终结果插入 nums 的前 k 个位置后返回 k 。

不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

判题标准:

系统会用下面的代码来测试你的题解:

int[] nums = […]; // 输入数组
int[] expectedNums = […]; // 长度正确的期望答案

int k = removeDuplicates(nums); // 调用

assert k == expectedNums.length; for (int i = 0; i < k; i++) { assert nums[i] == expectedNums[i]; }
如果所有断言都通过,那么您的题解将被 通过。

示例 1:

输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。

示例 2:

输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。

解题思路:

题目要求为传入一个数组,传出符合条件后的数组的长度,设置两个指针,分别为快指针和慢指针,快指针与慢指针的初始化均为1,因为0号元素一定是不需要变动位置的,排序从从小到大的顺序进行排序,块指针遍历整个数组元素,若nums[fast]!=nums[fast-1],则将nums[slow]=nums[fast],slow值加1.

class Solution {
public:int removeDuplicates(vector<int>& nums) {if(nums.size()==0)return 0;int fast=1,slow=1;int n=nums.size();while(fast<n){if(nums[fast]!=nums[fast-1]){nums[slow]=nums[fast];slow++;}fast++;}return slow;}
};

21. 合并两个有序链表

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

示例 1:

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例 2:

输入:l1 = [], l2 = []
输出:[]

示例 3:

输入:l1 = [], l2 = [0]
输出:[0]

解题思路:

将两个有序链表进行连接,将两个链表进行连接起来,不占用新的空间,常见一个新的头结点prevhead,定义一个新的指针prev指向prevhead,当两个链表均不为空时,对节点进行遍历,当list1->val<list2->val时,让prev指向list1,list1右移,当list2->val<list1->val时,让prev指向list2,list2右移,让prev=prev->next让prev向右移动,最后prev->next=list1==nullptr?list2:list1;list1是否为空,若是,则prev->next=list2,若不是空,则prev->next=list1.

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {ListNode * prevhead=new ListNode(-1);ListNode * prev=prevhead;while(list1!=nullptr&&list2!=nullptr){if(list1->val<list2->val){prev->next=list1;list1=list1->next;}else{prev->next=list2;list2=list2->next;}
prev=prev->next;}prev->next=list1==nullptr?list2:list1;return prevhead->next;}
};

2022/6/22

283.移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

输入: nums = [0]
输出: [0]

解题思路:双指针

1、定义两个指针i和k,初始化i = 0,k = 0。

2、i指针向后移动,遍整个nums数组,如果 nums[i] != 0,也就是说遇到了非0元素,此时我们就将nums[i]元素放置到nums[k]位置,同时k++后一位。

3、最后将k位置之后的元素都赋值为0。

实现细节:

遍历数组可以使用for(int x : nums),这样就少定义一个指针,代码也显得更加简洁。

时间复杂度分析: O(n)O(n) ,nn是数组的长度,每个位置只被遍历一次。

时间复杂度分析: O(1)O(1) ,只需要常数的空间存放指针变量。

class Solution {
public:void moveZeroes(vector<int>& nums) {int k = 0;for(int x : nums)if(x != 0) nums[k++] = x;while(k < nums.size())  nums[k++] = 0;        }
};

2022/6/23

27. 移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);
// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}

示例 1:

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。

示例 2:

输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。

解题思路:

设置双指针法,将left、right同时指向数组的第一个元素即a[0],首先遍历数组的所有元素,当元素不等于val值时,将右指针所指的值赋值给左指针所指向元素的值,同时左指针右移1个单位。当右指针访问遍历完整个数组后,返回左指针的值即可。

class Solution {
public:int removeElement(vector<int>& nums, int val) {int i=0;for(int x:nums){if(x!=val){nums[i]=x;i++;}}return i;}
};

26. 删除有序数组中的重复项

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。

更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

将最终结果插入 nums 的前 k 个位置后返回 k 。

不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

判题标准:

系统会用下面的代码来测试你的题解:

int[] nums = […]; // 输入数组
int[] expectedNums = […]; // 长度正确的期望答案
int k = removeDuplicates(nums); // 调用
assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
assert nums[i] == expectedNums[i];
}
如果所有断言都通过,那么您的题解将被 通过。

示例 1:

输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。

示例 2:

输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。

解题思路:

为首先设置双指针fast,slow指向nums[1],判断nums[fast]是否等nums[fast-1],若等于则fast++,即fast指针右移。若不等于,将fast指针指向的值赋值给slow指针指向的数字,即a[slow]=a[fast]然后将slow++,fast++,最后当fast遍历完整个数组后,返回slow即可。

class Solution {
public:int removeDuplicates(vector<int>& nums) {int fast=1;int slow=1;while(fast<nums.size()){if(nums[fast-1]!=nums[fast]){nums[slow]=nums[fast];slow++;}   fast++;}return slow;}
};

2022/6/24

80. 删除有序数组中的重复项 II

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);
// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}

示例 1:

输入:nums = [1,1,1,2,2,3]
输出:5, nums = [1,1,2,2,3]
解释:函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。 不需要考虑数组中超出新长度后面的元素。

示例 2:

输入:nums = [0,0,1,1,1,1,2,3,3]
输出:7, nums = [0,0,1,1,2,3,3]
解释:函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。 不需要考虑数组中超出新长度后面的元素。

解题思路:

首先设置双指针分别为fast和slow,让fast依次遍历访问每一个数组元素,因为由题意可知连续的2个元素相同时不改变,所以用nums[fast]与nums[slow-2]进行比较,若不相等,则将nums[fast]的值赋值给nums[slow],slow++,即向右移动一个单位。

class Solution {
public:int removeDuplicates(vector<int>& nums) {int fast=2;int slow=2;if(nums.size()<=2)return nums.size();while(fast<nums.size()){if(nums[fast]!=nums[slow-2]){nums[slow]=nums[fast];slow++;}fast++;}return slow;}
};

2022/6/25

75. 颜色分类

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

必须在不使用库的sort函数的情况下解决这个问题。

示例 1:

输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]

示例 2:

输入:nums = [2,0,1]
输出:[0,1,2]

解题思路为:

首先设置一个指针ptr指向nums[0],让0先排序到数组的前部分,然后让1排序到0元素的后面,最后剩余2。具体过程为首先遍历整个数组,让如果nums[i]==0时,让nums[i]与nums[ptr]进行交换,ptr++。当把0元素排序到数组的前面时,从ptr开始遍历剩下的元素,如果nums[i]==1时,并把nums[ptr]=nums[i],并让ptr++。
具体代码为:

class Solution {
public:void sortColors(vector<int>& nums) {int ptr=0;for(int i=0;i<nums.size();i++){if(nums[i]==0){swap(nums[i],nums[ptr]);ptr++; }} for(int i=ptr;i<nums.size();i++){if(nums[i]==1){swap(nums[i],nums[ptr]);ptr++;}}}
};

88. 合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

示例 1:

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。

示例 2:

输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。
合并结果是 [1] 。

示例 3:

输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。

解题思路为:
方法一:直接合并后排序

将nums2放进nums1的尾部,对整个数组进行排序。

时间复杂度为:O((m+n)log(m+n))。

空间复杂度为:O(log(m+n))。

排序序列长度为 m+n,套用快速排序的空间复杂度即可,平均情况为 O(log(m+n))。

代码为:

class Solution {
public:void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {for (int i = 0; i != n; ++i) {nums1[m + i] = nums2[i];}sort(nums1.begin(), nums1.end());}
};
方法二:

对2个数组nums1和nums2的元素进行比较,将小的元素放入到新生成的数组nums3当中。因为2个数组都是按从小到大的顺序进行的排序,当将一个数组当中的元素全部放入到nums3当中后,将另一个数组中的全部元素依次放入到nums3当中即可。

需要注意的是,首先判断nums1的元素是否遍历完了,若全部都访问了,则将数组nums2的全部元素都放入到nums3当中。

否则若数组nums2当中的全部元素都访问后,将nums1的元素放入到nums3当中。

否则,两个数组元素都没有被访问完,所以依次比较两个数组元素的大小

class Solution {
public:void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {vector<int> nums3(m+n);int i=0;int j=0;int temp;while(i<m||j<n){if(i==m){temp=nums2[j];j++;}else  if(j==n){temp=nums1[i];i++;}else if(nums1[i]<nums2[j]){temp=nums1[i];i++;}else{temp=nums2[j];j++;}nums3[i+j-1]=temp;}for(int i=0;i<m+n;i++){nums1[i]=nums3[i];}}
};

2022/7/4

125. 验证回文串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明:本题中,我们将空字符串定义为有效的回文串。

示例 1:

输入: “A man, a plan, a canal: Panama”
输出: true
解释:“amanaplanacanalpanama” 是回文串

示例 2:

输入: “race a car”
输出: false
解释:“raceacar” 不是回文串

解题思路:

设置左右指针分别指向字符串的首端和末端,依次比较所指向的数字是否相同?若相同则left++,right–,直至left==right时,则遍历结束。

注意:用到的API为isalnum()函数用来检测一个字符是否是字母或十进制数字。

返回值非0表示字符为字母或十进制数字,返回值为0表示字符为非字母或非十进制数字。

2.tolower()用来将大写字母返回为小写字母。

class Solution {
public:bool isPalindrome(string s) {int left=0;string tea;for(char c:s){if(isalnum(c)){tea+=tolower(c);}}
int right=tea.size()-1;while(left<right){if(tea[left]==tea[right]){left++;right--;}else{return false;break;}}return true;}
};

时间复杂度为:O(|s|),|s|为s的长度。

空间复杂度为:O(|s|),由于我们需要将所有的字母和数字字符存放在另一个字符串中,在最坏情况下,新的字符串与原字符串完全相同,因此需要使用O(|s|)的空间。

2022/7/5

345. 反转字符串中的元音字母

给你一个字符串 s ,仅反转字符串中的所有元音字母,并返回结果字符串。

元音字母包括 ‘a’、‘e’、‘i’、‘o’、‘u’,且可能以大小写两种形式出现。

示例 1:

输入:s = “hello”
输出:“holle”

示例 2:

输入:s = “leetcode”
输出:“leotcede”

解题思路:

利用双指针法,首先设置2个指针left、right分别指向字符串的第0个元素和最后一个元素,当left<right时,让left指针一直向右移动直到指向一个元音字母,同时,让right指针不停地向左移动,直到指向一个元音字母,此时,若left<right,让s[left]与s[right]交换,否则所有的元音字母都遍历过了,退出过程。

class Solution {
public:string reverseVowels(string s) {int left=0;int right=s.size()-1;char temp;while(left<right){while(left<right&&s[left]!='a'&&s[left]!='e'&&s[left]!='i'&&s[left]!='o'&&s[left]!='u'&&s[left]!='A'&&s[left]!='E'&&s[left]!='I'&&s[left]!='O'&&s[left]!='U'){left++;}while(left<right&&s[right]!='a'&&s[right]!='e'&&s[right]!='i'&&s[right]!='o'&&s[right]!='u'&&s[right]!='A'&&s[right]!='E'&&s[right]!='I'&&s[right]!='O'&&s[right]!='U'){right--;}if(left<right){swap(s[left],s[right]);left++;right--;}}return s;}
};

时间复杂度:O(n)

空间复杂度:O(1)或O(n)

11. 盛最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

在这里插入图片描述

示例 1:

输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例 2:

输入:height = [1,1]
输出:1

解题思路为:

双指针法,设置2个指针分别指向数组的首部第0个元素和尾部最后一个元素,设置能够盛水的最大值为min(height[left],height[right])*(right-left),在遍历完数组后输出最大的值,当left<right时比较height[left]与height[right]值的大小,若height[left]<height[right] left++,若height[left]>=height[right] right--

class Solution {
public:int maxArea(vector<int>& height) {int ans=0;int left=0;int right=height.size()-1;int sum=0;while(left<right){sum=min(height[left],height[right])*(right-left);ans=max(ans,sum);if(height[left]>=height[right]){right--;}else if(height[left]<height[right]){left++;}}
return ans;}
};

时间复杂度:O(n)
空间复杂度:O(1)

2022/7/6

141. 环形链表

题目:
给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

示例 1:

在这里插入图片描述

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

在这里插入图片描述

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

在这里插入图片描述

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

解题思路为:

使用双指针法.

本方法需要读者对「Floyd 判圈算法」(又称龟兔赛跑算法)有所了解。
假想「乌龟」和「兔子」在链表上移动,「兔子」跑得快,「乌龟」跑得慢。当「乌龟」和「兔子」从链表上的同一个节点开始移动时,如果该链表中没有环,那么「兔子」将一直处于「乌龟」的前方;如果该链表中有环,那么「兔子」会先于「乌龟」进入环,并且一直在环内移动。

等到「乌龟」进入环时,由于「兔子」的速度快,它一定会在某个时刻与乌龟相遇,即套了「乌龟」若干圈。

我们可以根据上述思路来解决本题。具体地,我们定义两个指针,一快一满。慢指针每次只移动一步,而快指针每次移动两步。初始时,慢指针在位置 head,而快指针在位置 head.next。这样一来,如果在移动的过程中,快指针反过来追上慢指针,就说明该链表为环形链表。否则快指针将到达链表尾部,该链表不为环形链表。

当块指针等于null或fast->next等于null时,跳出循环。

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:bool hasCycle(ListNode *head) {if(head==nullptr||head->next==nullptr){return false;}ListNode *slow=head;ListNode *fast=head->next;while(slow!=fast){if(fast==nullptr||fast->next==nullptr){return false; }slow=slow->next;fast=fast->next->next;}return true;}
};

这篇关于LeetCode新手村的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/702884

相关文章

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

leetcode-24Swap Nodes in Pairs

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode swapPairs(L

leetcode-23Merge k Sorted Lists

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode mergeKLists

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

【JavaScript】LeetCode:16-20

文章目录 16 无重复字符的最长字串17 找到字符串中所有字母异位词18 和为K的子数组19 滑动窗口最大值20 最小覆盖字串 16 无重复字符的最长字串 滑动窗口 + 哈希表这里用哈希集合Set()实现。左指针i,右指针j,从头遍历数组,若j指针指向的元素不在set中,则加入该元素,否则更新结果res,删除集合中i指针指向的元素,进入下一轮循环。 /*** @param

LeetCode:64. 最大正方形 动态规划 时间复杂度O(nm)

64. 最大正方形 题目链接 题目描述 给定一个由 0 和 1 组成的二维矩阵,找出只包含 1 的最大正方形,并返回其面积。 示例1: 输入: 1 0 1 0 01 0 1 1 11 1 1 1 11 0 0 1 0输出: 4 示例2: 输入: 0 1 1 0 01 1 1 1 11 1 1 1 11 1 1 1 1输出: 9 解题思路 这道题的思路是使用动态规划

LeetCode 第414场周赛个人题解

目录 Q1. 将日期转换为二进制表示 原题链接 思路分析 AC代码 Q2. 范围内整数的最大得分 原题链接 思路分析 AC代码 Q3. 到达数组末尾的最大得分 原题链接 思路分析 AC代码 Q4. 吃掉所有兵需要的最多移动次数 原题链接 思路分析 AC代码 Q1. 将日期转换为二进制表示 原题链接 Q1. 将日期转换为二进制表示 思路分析

【JavaScript】LeetCode:21-25

文章目录 21 最大子数组和22 合并区间23 轮转数组24 除自身以外数组的乘积25 缺失的第一个正数 21 最大子数组和 贪心 / 动态规划贪心:连续和(count)< 0时,放弃当前起点的连续和,将下一个数作为新起点,这里提供使用贪心算法解决本题的代码。动态规划:dp[i]:以nums[i]为结尾的最长连续子序列(子数组)和。 dp[i] = max(dp[i - 1]