Leetcode刷题 week 2
Leetcode 总题单:https://blog.csdn.net/m0_46272108/article/details/109269407
367.有效的完全平方数
本体的思想:
查找1~num,那么直接遍历的话时间复杂度是: O ( n ) O(n) O(n)
用二分查找时间复杂度是: O ( l o g n ) O(logn) O(logn)
C++代码
class Solution {
public:
bool isPerfectSquare(int num) {
int l = 1, r = num;
while (l < r) {
int mid = l + 1ll + r >> 1;//有可能爆int,1要改成longlong
if (mid <= num / mid) {
l = mid;//l = mid,上面必须要+1,否则可能会进入死循环
} else {
r = mid - 1;
}
}
return r * r == num;
}
};
Java代码
class Solution {
public boolean isPerfectSquare(int num) {
int l = 1, r = num;
while (l < r) {
int mid = l + 1 + r >> 1;
if (mid <= num / mid) {
l = mid;//l = mid,上面必须要+1,否则可能会进入死循环
} else {
r = mid - 1;
}
}
return r * r == num;
}
}
371.两整数之和
这道题,要求不用 + - ,计算 a+b
^异或运算有另一种说法:不进位加法
举个例子:
1 1 0 1
1 0 1 1
———
0 1 1 0
就是没有进位。
那么我们可以通过 按位与运算 来进行 “进位” 操作。
例子:
1 1 0 1
1 0 1 1
———
1 0 0 1
再进位就是 << 1左移一位。
结果就是1 0 0 1 0
原本的结果:1101 + 1011 = 11000
0110 + 10010 = 11000
结果一致。
所以a+b 等价于 [(a & b) << 1] + (a ^ b)
这样还是会有加号。
因为题目要求是int的,且int只有32位。
每执行一次 a 的末尾就会多一个0
那么最多执行32次,a的值就为0,b的值就是最终的结果。
C++代码
class Solution {
public:
int getSum(int a, int b) {
if (!a) return b;
int sum1 = a ^ b;
int sum2 = (unsigned)(a & b) << 1;
return getSum(sum2, sum1);
}
};
Java代码
class Solution {
public int getSum(int a, int b) {
if (a == 0) return b;
int sum1 = a ^ b;
int sum2 = (a & b) << 1;
return getSum(sum2, sum1);
}
}
374.猜数字大小
本体思想也是二分搜索:
直接砍一半,搜索比线性快:
上代码:
C++代码
/**
* Forward declaration of guess API.
* @param num your guess
* @return -1 if num is lower than the guess number
* 1 if num is higher than the guess number
* otherwise return 0
* int guess(int num);
*/
class Solution {
public:
int guessNumber(int n) {
int l = 1, r = n;
while (l < r) {
int mid = (long long)l + r >> 1;//爆int
if (guess(mid) <= 0)
r = mid;
else
l = mid + 1;
}
return r;
}
};
383.赎金信
题意:判断第一个字符串ransom能不能由第二个字符串magazines里面的字符串构成。
思路:
开map存字符串magazine,并且统计字符串magazine里面的字符数
然后开map存字符串ransom,遍历字符串ransom,如果字符串magazine里面没有字符串ransom里的某个字符串,那么就直接返回false,如果有,就在字符串magazine里面的对应字符-1,如果遍历完字符串ransom,都没有返回false的话,那么就是 第一个字符串ransom可以由第二个字符串magazine里面的字符构成。就返回true;
上代码:
C++代码
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
unordered_map<char, int> hash;
for(auto x : magazine) hash[x]++;
for(auto x : ransomNote)
if(!hash[x])
return false;
else
hash[x]--;
return true;
}
};
387.字符串中的第一个唯一字符
思路:
1.开map,存这个字符串,对每一个字符进行计数
2.从头到尾遍历一遍,找到字符数第一个==1的字符对应下标输出即可。
C++代码
class Solution {
public:
int firstUniqChar(string s) {
unordered_map<char, int> hash;
for (auto x : s) hash[x]++;
for (int i = 0; i < s.size(); ++i) {
if (hash[s[i]] == 1) {
return i;
}
}
return -1;
}
};
Java代码
class Solution {
public int firstUniqChar(String s) {
int[] a = new int[26];
// Arrays.fill(a, 0);
for (int i = 0; i < s.length(); ++i) {
a[s.charAt(i) - 'a']++;
}
for (int i = 0; i < s.length(); ++i) {
if (a[s.charAt(i) - 'a'] == 1)
return i;
}
return -1;
}
}
389.找不同
异或的运用。
全部异或一遍即可。
使用异或运算可以解题主要因为异或运算有以下几个特点:
- 一个数和0做异或运算等于本身:a⊕0 = a
- 一个数和其本身做XOR运算等于 0:a⊕a = 0
- 异或运算满足交换律和结合律:a⊕b⊕a = (a⊕a)⊕b = 0⊕b = b
故而在以上的基础条件上,将所有数字按照顺序做抑或运算,最后剩下的结果即为唯一的数字
C++代码
class Solution {
public:
char findTheDifference(string s, string t) {
char ch = 0;
for (int i = 0; i < s.size(); ++i) {
ch ^= s[i] ^ t[i];
}
return ch ^ t[t.size() - 1];
}
};
Java代码
class Solution {
public char findTheDifference(String s, String t) {
char ch = 0;
for (int i = 0; i < s.length(); ++i) {
ch ^= s.charAt(i) ^ t.charAt(i);
}
ch ^= t.charAt(t.length() - 1);
return ch;
}
}
392.判断子序列
思路:双指针思想
C++代码
class Solution {
public:
bool isSubsequence(string s, string t) {
int i = 0;
for (int j = 0; i < s.size() && j < t.size(); ++j) {
if (s[i] == t[j]) {
i++;
}
}
return i == s.size();
}
};
Java代码
class Solution {
public boolean isSubsequence(String s, String t) {
int i = 0;
for (int j = 0; i < s.length() && j < t.length(); ++j) {
if (s.charAt(i) == t.charAt(j)) {
i++;
}
}
return i == s.length();
}
}