文章目录
367. Valid Perfect Square
Given a positive integer num
, write a function which returns True if num
is a perfect square else False.
Note: Do not use any built-in library function such as sqrt
.
Example 1:
Input: 16
Output: true
Example 2:
Input: 14
Output: false
Solution in C++:
关键点:
- 哈喽
思路:
- 开始想着之前好像也有手写过sqrt的实现方法。然后记忆里面就有n/2这么个数存在,但是我举了几个例子,发现对于是平方的数这个适用但是对于不是的就不是很适用,但是发现加完1之后就都适用了,所以就产生了以下的方法。
- 在discuss里面看到了一个不是很理解但感觉很厉害的方法。平方根倒数速算法。数学之美:平方根倒数速算法中的神奇数字 0x5f3759df
方法一:暴力法
bool isPerfectSquare(int num) {
if (num < 0)
return false;
for(int i = 1; i <= floor(num/2) + 1; ++i)
{
if ( i*i == num)
return true;
}
return false;
}
方法二:平方根倒数速算法
float InvSqrt (float x) {
float half = 0.5 * x;
int i = *((int *)&x);
i = 0x5f3759df - (i >> 1);
x = *((float *)&i);
x = x * (1.5 - (half * x * x));
return x;
}
371. Sum of Two Integers
Calculate the sum of two integers a and b, but you are not allowed to use the operator +
and -
.
Example 1:
Input: a = 1, b = 2
Output: 3
Example 2:
Input: a = -2, b = 3
Output: 1
Solution in C++:
关键点:
- 计算机计算本质
思路:
- 一开始确实让我有点为难,毕竟人类的思维一直都是四则运算法则。但是当我想到数字在计算机中是二进制表示的时候,就发现直接用位运算进行代替即可。这里的思路是,当将a & b时得到的是未加上进位的结果,所以还需要不断的加进位的结果,得到进位通过a ^ b即可,但是需要加到a & b的结果中还需要将进位再左移1位。如此反复直到无进位为止即为所求。
int getSum(int a, int b) {
// 进位
int carry = (a & b) << 1;
int result = a ^ b;
while(carry){
int tmp = result;
result = result ^ carry;
carry = (tmp & carry) << 1;
}
return result;
}
374. Guess Number Higher or Lower
We are playing the Guess Game. The game is as follows:
I pick a number from 1 to n. You have to guess which number I picked.
Every time you guess wrong, I’ll tell you whether the number is higher or lower.
You call a pre-defined API guess(int num)
which returns 3 possible results (-1, 1, or 0):
-1 : My number is lower
1 : My number is higher
0 : Congrats! You got it!
Example :
Input: n = 10, pick = 6
Output: 6
Solution in C++:
关键点:
- 函数返回值的含义(不要弄反了)
思路:
- 感觉看到题目就是很明显的二分查找。
- 再看解析部分,有三分的查找的方法,比二分加快了一些。
方法一:二分查找
// Forward declaration of guess API.
// @param num, your guess
// @return -1 if my number is lower, 1 if my number is higher, otherwise return 0
int guess(int num);
class Solution {
public:
int guessNumber(int n) {
int left = 1;
int right = n;
while(left < right){
int mid = left + (right - left) / 2;
int result = guess(mid) ;
if (result == 0)
return mid;
else if (result == 1) // 猜小了
{
left = mid + 1;
} else {
right = mid - 1;
}
}
return left;
}
};
方法二:三分查找
int guessNumber(int n) {
int low = 1;
int high = n;
while(low < high){
int mid1 = low + (high - low) / 3;
int mid2 = high - (high - low) / 3;
int res1 = guess(mid1);
int res2 = guess(mid2);
if (res1 == 0)
return mid1;
else if (res2 == 0)
return mid2;
else if (res1 < 0) // pick比mid1还小
high = mid1 - 1;
else if (res2 > 0) // pick比mid2还大
low = mid2 + 1;
else{ // pick位于mid1与mid2之间
low = mid1 + 1;
high = mid2 - 1;
}
}
return low;
}
383. Ransom Note
Given an arbitrary ransom note string and another string containing letters from all the magazines, write a function that will return true if the ransom note can be constructed from the magazines ; otherwise, it will return false.
Each letter in the magazine string can only be used once in your ransom note.
Note:
You may assume that both strings contain only lowercase letters.
canConstruct("a", "b") -> false
canConstruct("aa", "ab") -> false
canConstruct("aa", "aab") -> true
Solution in C++:
关键点:
- 字母
思路:
- 开始还没太读懂题意,就测试了几个输入样例。ab ba返回为true,再加上给的样例,大概懂了。字母是可以重复的但是需要在另一个字符串中也出现,有点像求子串但是不同的是这个子串的顺序可以随意。然后题目中只要求字母,这里我就采用map<char,int>,第一遍扫描magazine字符串获取每个字母的次数,然后再扫描ransomNote,如果在map中没有的字母则返回false,有的字母则数量减一,看最后是否会减到小于0
bool canConstruct(string ransomNote, string magazine) {
size_t nsize = ransomNote.size();
size_t msize = magazine.size();
if (nsize > msize)
return false;
map<char,int> mtable;
for(auto le : magazine){
map<char,int>::iterator it = mtable.find(le);
if (it != mtable.end())
++mtable[le];
else
mtable[le] = 1;
}
for(auto le : ransomNote){
map<char,int>::iterator it = mtable.find(le);
if (it == mtable.end())
return false;
else{
--mtable[le];
if (mtable[le] < 0)
return false;
}
}
return true;
}
小结
今天收获还蛮多的,第一题的平方根倒数速算法,虽然还有些没有太懂,但是整体来说还是给了我一个新的思维。然后再就是第二题用计算机思维来做题。第三题的三分查找,第四题算是巩固了字符串处理的这种思考方式。
知识点
- 平方根倒数速算法
- 三分查找、二分查找(减法写法)
- 位运算求加法