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

猜你喜欢

转载自blog.csdn.net/m0_46272108/article/details/109301316