202. 快乐数
编写一个算法来判断一个数
n
是不是快乐数。「快乐数」 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数。
如果
n
是 快乐数 就返回true
;不是,则返回false
。
int getsum(int n){
int sum = 0;
while(n){
sum += (n % 10) * (n % 10);
n = n / 10;
}
return sum;
}
class Solution {
public:
bool isHappy(int n) {
unordered_set<int> set;
int sum = 0;
while(1){
sum = getsum(n);
if(sum == 1) return true;
if(set.find(sum) != set.end()){ // 如果重复,则说明陷入循环,返回false
return false;
}
else{
set.insert(sum); // 不重复就继续添加进set
}
n = sum; // sum总和 作为迭代,进入下一个循环
}
}
};
// 还可以双指针法,可以试一试!
1. 两数之和
题目:给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
作为leecode第一题,其实也能用哈希表来解决:
因为只有两个数,所以可以用target - nums[i]来做为检索,在遍历中找到答案
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> result;
unordered_map<int, int> map; // 不重复的map——key,value
for(int i = 0; i < nums.size(); i++){
auto it = map.find(target - nums[i]);
if(it == map.end()){ // 到末尾说明没有找到
map.insert(pair<int, int>(nums[i], i)); // 作为新的元素对加入map中,方便之后检索
}
else{ // 找到了的话
result.push_back(it->second);
result.push_back(i); // 将map检索到的元素(key)对应下标(value) 和 当前匹配的下标都放进数组里
}
}
return result;
}
};
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
本题从四个数组中找元素,而且只需要返回次数,还是挺简单的:
map的键值key为数字和,value是和的次数
在累加次数时,注意要累加value,而不是仅仅count++
class Solution {
public:
int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
unordered_map<int, int> map;
int count = 0;
int target = 0;
for(int a : A){
for(int b : B){
map[a + b]++;
}
}
for(int c : C){
for(int d : D){
target = 0 - (c + d); // 目标为cd之和的相反数
if(map.find(target) != map.end()){ // 之前存储的ab之和中找到了
count += map[target]; // map[target]值为该键值的次数
}
}
}
return count;
}
};
383. 赎金信
给你两个字符串:
ransomNote
和magazine
,判断ransomNote
能不能由magazine
里面的字符构成。如果可以,返回
true
;否则返回false
。
magazine
中的每个字符只能在ransomNote
中使用一次。
看到英文字母,看到xx里面有没有xx元素------>哈希表法,数组解决
注意:先将mag(供)的字母全部放进数组里,然后在ran(求)直接中找字母是否对应,如果ran其中一个字母个数大于mag,就可以提前结束循环!
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
// 因为只能用一次,所以当ran中的字符个数大于mag,返回false
if(ransomNote.size() > ransomNote.size()) return false;
int nums[26] = {0};
// 先供
for(int i = 0; i < magazine.size(); i++){
nums[magazine[i] - 'a']++;
}
// 后需
for(int i = 0; i < ransomNote.size(); i++){
nums[ransomNote[i] - 'a']--;
if(nums[ransomNote[i] - 'a'] < 0){ // 需 > 供,直接返回
return false;
}
}
// 循环完整遍历,说明供》需
return true;
}
};
15. 三数之和
class Solution{
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
// sort(nums);
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size(); i++){
if(nums[0] > 0) return result; // 排序后第一个数就大于零,三叔之和就不可能等于0
// 对第一个元素(遍历)也要去重
if(i > 0 && nums[i] == nums[i - 1]) continue;
int left = i + 1, right = nums.size() - 1;
while(left < right){
int sum = nums[i] + nums[left] + nums[right];
if(sum > 0) right--;
else if(sum < 0) left++;
else{
// 等于0,装入容器中
result.push_back({nums[i], nums[left], nums[right]});
// 要查重
while(right > left && nums[left] == nums[left + 1]){
left++;
}
while(right > left && nums[right] == nums[right - 1]){
right--;
}
left++;
right--; // 要加上,指向下一个不同的元素
}
}
}
return result;
}
};
18. 四数之和
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result;
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size(); i++){
if(nums[i] > target && nums[i] >= 0) break; // 一级剪枝
if(i > 0 && nums[i] == nums[i - 1]){ // 一级去重
continue; // 重复就进入下一个循环
}
for(int j = i + 1; j < nums.size(); j++){
if(nums[i] + nums[j] > target && nums[i] + nums[j] >= 0) break; // 二级剪枝
if(j > i + 1 && nums[j] == nums[j - 1]){ // 二级去重
continue; // 重复就进入下一个循环
}
int left = j + 1, right = nums.size() - 1;
while(left < right){
long sum = (long)nums[i] + nums[j] + nums[left] + nums[right];
if(sum > target) right--;
else if(sum < target) left++;
else{
result.push_back({nums[i], nums[j], nums[left], nums[right]});
// 去重
while(left < right && nums[left] == nums[left + 1]) left++;
while(left < right && nums[right] == nums[right - 1]) right--;
left++;
right--;
}
}
}
}
return result;
}
};