[日常刷題]leetcode D29
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之後就都適用了,所以就產生了以下的方法。
方法一:暴力法
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;
}
小結
今天收穫還蠻多的,第一題的平方根倒數速演算法,雖然還有些沒有太懂,但是整體來說還是給了我一個新的思維。然後再就是第二題用計算機思維來做題。第三題的三分查詢,第四題算是鞏固了字串處理的這種思考方式。
知識點
- 平方根倒數速演算法
- 三分查詢、二分查詢(減法寫法)
- 位運算求加法