技巧【Lecode_HOT100】

1.只出现一次的数字No.136

image-20241226224656282

  • 方法一:异或
public class Solution {
    public int singleNumber(int[] nums) {
        int result = 0;
        for (int num : nums) {
            result ^= num;  // 对数组中的每个元素进行异或操作
        }
        return result;  // 最终结果就是只出现一次的元素
    }
}
  • 方法二 哈希表,不满足线性时间复杂度
import java.util.HashMap;

public class Solution {
    public int singleNumber(int[] nums) {
        // 创建一个哈希表
        HashMap<Integer, Integer> map = new HashMap<>();
        
        // 遍历数组,统计每个数字出现的次数
        for (int num : nums) {
            map.put(num, map.getOrDefault(num, 0) + 1);
        }
        
        // 遍历哈希表,找出只出现一次的数字
        for (int num : map.keySet()) {
            if (map.get(num) == 1) {
                return num;
            }
        }
        
        // 如果没有找到(理论上不会发生),返回 -1 或其他特殊值
        return -1;
    }
}

  • 方法三 集合 不满足线性时间复杂度
import java.util.HashSet;

public class Solution {
    public int singleNumber(int[] nums) {
        // 创建一个空的哈希集合
        HashSet<Integer> set = new HashSet<>();
        
        // 遍历数组中的每个数字
        for (int num : nums) {
            // 如果集合中没有该数字,则加入集合
            if (!set.contains(num)) {
                set.add(num);
            } else {
                // 如果集合中已经有该数字,则删除它
                set.remove(num);
            }
        }
        
        // 最后集合中只会剩下那个只出现一次的数字
        return set.iterator().next();  // 获取集合中的第一个元素
    }
}

  • 方法四 元素之和 不满足线性时间复杂度
import java.util.HashSet;

public class Solution {
    public int singleNumber(int[] nums) {
        // 创建一个哈希集合
        HashSet<Integer> set = new HashSet<>();
        
        // 计算数组的元素之和
        int sumArray = 0;
        
        // 将数组中的元素添加到集合,并计算数组元素的总和
        for (int num : nums) {
            set.add(num);
            sumArray += num;
        }
        
        // 计算集合中所有元素的和
        int sumSet = 0;
        for (int num : set) {
            sumSet += num;
        }
        
        // 使用数学公式计算只出现一次的数字
        return 2 * sumSet - sumArray;
    }
}

2.多数元素No.169

image-20241227090832029

image-20241227091326948

  • 方法一:Boyer-Moore 投票算法
public class Solution {
    public int majorityElement(int[] nums) {
        int candidate = nums[0];
        int count = 1;
        
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] == candidate) {
                count++;
            } else {
                count--;
            }
            
            if (count == 0) {
                candidate = nums[i];
                count = 1;
            }
        }
        
        return candidate; // 最后的候选者即为多数元素
    }
}

  • 方法二:哈希表 不满足空间复杂度
public int majorityElement(int[] nums) {
        HashMap<Integer,Integer> map = new HashMap<>();
        for(int num:nums){
            map.put(num,map.getOrDefault(num,0)+1);
        }
        for(int key:map.keySet()){
            if(map.get(key)>nums.length/2){
                return key;
            }
        }
        return -1;
    }
  • 方法三:排序数组
public int majorityElement(int[] nums) {
        Arrays.sort(nums);
        return nums[nums.length/2];
    }
3.颜色分类No.75

image-20241227121435478

  • 三路快排
public class Solution {
    public void sortColors(int[] nums) {
        int low = 0, mid = 0, high = nums.length - 1;
        
        while (mid <= high) {
            if (nums[mid] == 0) {
                // 如果是0,放到左侧区域
                swap(nums, low, mid);
                low++;
                mid++;
            } else if (nums[mid] == 1) {
                // 如果是1,保持在中间区域
                mid++;
            } else {
                // 如果是2,放到右侧区域
                swap(nums, mid, high);
                high--;
            }
        }
    }
    
    // 辅助方法:交换数组中的两个元素
    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

4.下一个排列No.31

image-20241228092341053

public void nextPermutation(int[] nums) {
    int n = nums.length;
    
    // Step 1: 找到第一个逆序对
    int i = n - 2;
    while (i >= 0 && nums[i] >= nums[i + 1]) {
        i--;
    }
    
    // 如果找到了逆序对,处理交换
    if (i >= 0) {
        // Step 2: 找到比 nums[i] 大的最小元素
        int j = n - 1;
        while (nums[j] <= nums[i]) {
            j--;
        }
        
        // Step 3: 交换 nums[i] 和 nums[j]
        swap(nums, i, j);
    }
    
    // Step 4: 反转 nums[i + 1] 到末尾的部分
    reverse(nums, i + 1);
}

private void swap(int[] nums, int i, int j) {
    int temp = nums[i];
    nums[i] = nums[j];
    nums[j] = temp;
}

private void reverse(int[] nums, int start) {
    int i = start, j = nums.length - 1;
    while (i < j) {
        swap(nums, i, j);
        i++;
        j--;
    }
}
5.寻找重复数No.287
  • 快慢指针法

image-20241227214304275

public class Solution {
    public int findDuplicate(int[] nums) {
        // 快慢指针初始化
        int slow = nums[0];
        int fast = nums[0];
        
        // 第一次相遇:快慢指针进入环内
        do {
            slow = nums[slow];         // 慢指针每次走一步
            fast = nums[nums[fast]];   // 快指针每次走两步
        } while (slow != fast);
        
        // 第二次相遇:寻找环的入口
        slow = nums[0];  // 重置慢指针到起始位置
        while (slow != fast) {
            slow = nums[slow];     // 慢指针每次走一步
            fast = nums[fast];     // 快指针每次走一步
        }
        
        return slow;  // 返回环的入口,即重复的数字
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值