剑指 Offer 15. 二进制中1的个数

请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。例如,把 9 表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2

思路:
位运算。和 1 进行“与”操作,然后将 n 右移一位,直到 n 等于 0

  1. public class Solution {
  2. // you need to treat n as an unsigned value
  3. public int hammingWeight(int n) {
  4. int res = 0;
  5. while(n != 0) {
  6. if((n&1) == 1) res++;
  7. n = n>>>1;
  8. }
  9. return res;
  10. }
  11. }

剑指 Offer 56 - I. 数组中数字出现的次数

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

思路1:
栈。
执行用时:17 ms, 在所有 Java 提交中击败了7.23%的用户
内存消耗:41.8 MB, 在所有 Java 提交中击败了100.00%的用户

  1. class Solution {
  2. public int[] singleNumbers(int[] nums) {
  3. int[] res = new int[2];
  4. Arrays.sort(nums);
  5. Stack<Integer> stack = new Stack<>();
  6. for (int num : nums) {
  7. if (stack.isEmpty() || stack.peek() != num) {
  8. stack.push(num);
  9. } else if (stack.peek() == num) {
  10. stack.pop();
  11. }
  12. }
  13. res[0] = stack.pop();
  14. res[1] = stack.pop();
  15. return res;
  16. }
  17. }

思路2:
分组异或。
执行用时:2 ms, 在所有 Java 提交中击败了97.28%的用户
内存消耗:41.4 MB, 在所有 Java 提交中击败了60.78%的用户

  1. class Solution {
  2. public int[] singleNumbers(int[] nums) {
  3. int sum = 0;
  4. int[] res = new int[2];
  5. for(int num : nums){
  6. sum ^= num;
  7. }
  8. int lowbit = sum & (-sum);
  9. for(int num : nums){
  10. if((num & lowbit) == 0){
  11. res[0] ^= num;
  12. }else{
  13. res[1] ^= num;
  14. }
  15. }
  16. return res;
  17. }
  18. }

剑指 Offer 56 - II. 数组中数字出现的次数 II

在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。

思路:
哈希表。
执行用时:16 ms, 在所有 Java 提交中击败了47.02%的用户
内存消耗:41 MB, 在所有 Java 提交中击败了100.00%的用户

  1. class Solution {
  2. public int singleNumber(int[] nums) {
  3. HashMap<Integer, Integer> map = new HashMap<>();
  4. for (int num : nums) {
  5. map.put(num, map.getOrDefault(num,0)+1);
  6. }
  7. for (int k : map.keySet()) {
  8. if (map.get(k) == 1) return k;
  9. }
  10. return -1;
  11. }
  12. }

思路2:
异或。

  1. class Solution {
  2. public int singleNumber(int[] nums) {
  3. int a = 0;
  4. int b = 0;
  5. for(int num : nums) {
  6. a = (a ^ num) & ~b;
  7. b = (b ^ num) & ~a;
  8. }
  9. return a;
  10. }
  11. }

剑指 Offer 65. 不用加减乘除做加法

写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。

思路:
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:36.2 MB, 在所有 Java 提交中击败了100.00%的用户

  1. class Solution {
  2. public int add(int a, int b) {
  3. int sum = a ^ b;
  4. int carry = (a & b) << 1;
  5. while(carry != 0) {
  6. int temp = sum;
  7. sum = sum ^ carry;
  8. carry = (temp & carry) << 1;
  9. }
  10. return sum;
  11. }
  12. }