0
点赞
收藏
分享

微信扫一扫

LeetCode刷题day24


​​202. 快乐数​​

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」定义为:

对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果 可以变为 1,那么这个数就是快乐数。
如果 n 是快乐数就返回 true ;不是,则返回 false 。

示例 1:

输入:n = 19
输出:true

解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

示例 2:

输入:n = 2
输出:false

思路分析:

注意题目中的可能会无限循环,也就是说在求和的过程中,sum会重复出现.

  • 所以我们就可以对该数进行快乐的判断,每次如果不是1,说明该数目前不是快乐数.
  • 同时要在set中寻找该数是否曾经出现过,如果出现过则说明出现了循环则一定不是快乐数.
  • 如果还没有出现则持续进行判断…

参考代码

int getSum(int n){
int sum = 0;
while(n){
sum+= (n%10)*(n%10);
n /= 10;
}
return sum;
}

//由于只需要存这个元素在集合中是否存在,而且不需要重复,所以我们使用unordered_set
bool isHappy(int n) {
unordered_set<int> S;
int temp;
while(1){
temp = getSum(n);
if(temp==1){
return true;
}
if(S.find(temp)!=S.end()){
return false;
}else{
S.insert(temp);
}
n = temp;
}

}

​​1. 两数之和​​

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]

解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

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

示例 3:

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

方法一:暴力法

参考代码

vector<int> twoSum(vector<int>& nums, int target) {
for(int i = 0; i < nums.size()-1; i++) {
for(int j = i+1; j < nums.size(); j++) {
if(nums[i]+nums[j]==target) {

return {i,j};
}
}
}
return {};
}

  • 时间复杂度:LeetCode刷题day24_leetcode
  • 空间复杂度:LeetCode刷题day24_leetcode_02

方法二:hash表

  • 因为每次不仅要存数,还要存储其下标,所以我们使用map,因为不需要有序和重复性,我们可以选择:unordered_map M
  • 用i遍历所有的元素,在M中查找是否存在元素 target - nums[i],如果存在则说明找到了,返回当前元素和这个元素的下标.
  • 如果没有找到则将当前元素和下标插入到M中.

参考代码2

vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> M;
for(int i = 0;i < nums.size();i++){
if(M.find(target-nums[i])!=M.end()){
return {M[target-nums[i]],i};
}else{
M[nums[i]] = i;
}
}
return {};
}

  • 时间复杂度:LeetCode刷题day24_数组_03
  • 空间复杂度:LeetCode刷题day24_数组_03

​​15. 三数之和​​

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

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

示例 2:

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

示例 3:

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

思路分析

排序 + 双指针

算法流程:

(1). 特判,对于数组长度 n,如果数组长度小于 3,返回 []。
(2). 对数组进行排序。
(3).遍历排序后数组:

  • 若 nums[i]>0:因为已经排序好,所以后面不可能有三个数加和等于 0,直接返回结果。
  • 对nums[i] (代表的就是a)进行去重.
  • 令左指针 L=i+1,右指针 R=n-1,当 L<R 时,执行循环:

(4) 当 nums[i]+nums[L]+nums[R]==0执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 L,R 移到下一位置,寻找新的解
(5).若和大于 0,说明nums[R] 太大,R左移
(6).若和小于 0,说明 nums[L] 太小,L右移

复杂度分析

  • 时间复杂度:O(n^2)
    数组排序 O(n logn),遍历数组O(n),双指针遍历 O(n),总体 O(n logn)+O(n)∗O(n),
  • 空间复杂度:O(1)

参考代码

vector<vector<int>> threeSum(vector<int>& nums) {
if(nums.size()<3) {
return {};
}
sort(nums.begin(),nums.end());
if(nums[0]>0) {
return {};
}
vector<vector<int>> res;
int len = nums.size();
for(int i = 0; i < len; i++) {
if(nums[i]>0) { //如果当前的最小的值都>0,则后续的肯定也>0
return res;
}
if(i>0&&nums[i]==nums[i-1]) {// a元素进行去重...
continue;
}
int L = i+1;
int R = len - 1;
while(L<R) {
int X = nums[i]+nums[L]+nums[R];
if(!X) {
res.push_back({nums[i],nums[L],nums[R]});
//进行去重
while(L+1 <R&&nums[L]==nums[L+1]) {
L++;
}
while(R-1>L&&nums[R]==nums[R-1]) {
R--;
}
L++;
R--;
} else if(X>0) {
R--;

} else if(X<0) {
L++;
}

}
}
return res;
}

​​18. 四数之和​​

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。

示例 1:

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

示例 2:

输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]

思路分析

和三数之和解决思路基本一致,三数之和只是 i 固定,左右指针进行变化.
四数之和是i,j固定,然后左右指针进行变化,当左右指针变化一轮后,j进行后移一位.j移动完一轮后,i后移一位…

实现代码

vector<vector<int>> fourSum(vector<int>& nums, int target) {
if(nums.size()<4) {
return {};
}
int len = nums.size();
sort(nums.begin(),nums.end());
long temp,a,b,c,d;
vector<vector<int>> res;

for(a = 0; a<= len-4; a++) {
//对a去重
if(a>0&&nums[a]==nums[a-1]) { //进行下一个.
continue;
}
for(b = a+1; b<=len-3; b++) {
c = b+1;
d = len - 1;
if(b>a+1 && nums[b]==nums[b-1]) { //b去重
continue;
}
while(c<d) {
temp = 0;
temp += nums[a];
temp += nums[b];
temp+=nums[c];
temp+=nums[d];
if(temp==target) {
res.push_back({nums[a],nums[b],nums[c],nums[d]});
while(c+1<d && nums[c]==nums[c+1]) {
c++;
}
while(d-1>c&&nums[d]==nums[d-1]) {
d--;
}
c++;
d--;
}else if(temp > target){
d--;
} else{
c++;
}

}

}
}
return res;
}

​​454. 四数相加 II​​

给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:

0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

示例 1:

输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]
输出:2

解释:
两个元组如下:

  1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0
  2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0

示例 2:

输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0]
输出:1

思路分析

  • 首先定义 一个unordered_map,key放a和b两数之和,value 放a和b两数之和出现的次数。
  • 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。
  • 定义int变量cnt,用来统计a+b+c+d = 0 出现的次数。
  • 在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。
  • 最后返回统计值 cnt就可以了

参考代码

int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int,int> M;
int cnt = 0;
for(int A : nums1){
for(int B: nums2){
if(M.find(A+B)==M.end()){
M[A+B] = 1;
}else{
M[A+B]++;
}
}
}

for(int C:nums3){
for(int D: nums4){
if(M.find(0-C-D)!=M.end()){
cnt+=M[0-C-D];
}
}
}
return cnt;
}


举报

相关推荐

上好的刷题Day24

day24

寒假:Day24

Day24 | 每天五道题

国庆练习(Day24)

day24 树和算法

0 条评论