[日常刷题]leetcode D29

版权声明:希望各位多提意见多多互相交流哦~ https://blog.csdn.net/wait_for_taht_day5/article/details/82973948

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;
    }

小结

今天收获还蛮多的,第一题的平方根倒数速算法,虽然还有些没有太懂,但是整体来说还是给了我一个新的思维。然后再就是第二题用计算机思维来做题。第三题的三分查找,第四题算是巩固了字符串处理的这种思考方式。

知识点

  • 平方根倒数速算法
  • 三分查找、二分查找(减法写法)
  • 位运算求加法

猜你喜欢

转载自blog.csdn.net/wait_for_taht_day5/article/details/82973948