LeetCode Hot100(持续更新中)

一、哈希

(一)两数之和

思路一:传统方法-双层循环遍历
时间复杂度:O(n^2)

空间复杂度:O(1)

class Solution {
    public int[] twoSum(int[] nums, int target) {
        // 两层循环求解 时间复杂度O(N^2) 空间复杂度O(1)
        int[] goal = new int[2];

        for (int i = 0; i < nums.length - 1; i++) {
            for (int j = i+1; j < nums.length; j++) {
                if ( (nums[i] + nums[j]) == target ) {
                    goal[0] = i;
                    goal[1] = j;
                    return goal;
                }
            }
        }

        throw new IllegalArgumentException("no such two nums.");
    }
}

思路二:HashMap方法-一次遍历
时间复杂度:O(n)

空间复杂度:O(n)

class Solution {
    public int[] twoSum(int[] nums, int target) {
        // HashMap求解 时间复杂度O(N) 空间复杂度O(N)
        Map<Integer, Integer> numsMap = new HashMap();

        numsMap.put(nums[0], 0);

        for (int i = 1; i < nums.length; i++) {
            // 计算当前值距离目标值的补数
            int complement = target - nums[i];
            // 查看当前补数是否存在numsMap中
            if (numsMap.containsKey(complement)) {
                return new int[] { numsMap.get(complement), i};
            }
            // 不存在,将当前值加入numsMap中
            numsMap.put(nums[i], i);
        }

        throw new IllegalArgumentException("未找到符合要求的两个下标");
        
    }
}

(二)字母异位词分组

思路:采用哈希+排序

时间复杂度:O(N*M log M)  N为字符串数组长度,M为字符串长度

空间复杂度:O(N*M)

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
		// 字母异位词分组
		// 时间复杂度 O(N*MlogM)  N为字符串数组长度,M为字符串长度
		// 空间复杂度 O(N*M) 
		
		// 创建一个HashMap,键存储排序后的字符串,值存储字母异位词
		Map<String, List<String>> anagramMap = new HashMap<>();
		
		// 遍历字符串数组
		for (String str : strs) {
			// 对字符串重新进行排序
			char[] chars = str.toCharArray();
			Arrays.sort(chars);
			String sortedStr = new String(chars);
			
			// 如果哈希表不存在该字符串,则添加
			if ( !anagramMap.containsKey(sortedStr) ) {
				// 哈希表新增
				anagramMap.put(sortedStr, new ArrayList<>());
			}
			// 哈希表value赋值
			anagramMap.get(sortedStr).add(str);
		}
		
		return new ArrayList<>(anagramMap.values());
    }
}

(三)最长连续序列

思路一:常规解法:数组排序;双层循环遍历,找出最大的length

时间复杂度为:O(N*logN) + O(N^2)

空间复杂度:O(1)

思路二:哈希解法 要去重->HashSet

时间复杂度:O(N)

空间复杂度:O(N)

class Solution {
    public int longestConsecutive(int[] nums) {
		// 哈希解法 要去重 -> HashSet  时间复杂度:O(N)  空间复杂度:O(N)
		Set<Integer> numSet = new HashSet<>();
		
		// 遍历nums,加入numSet
		for (int num : nums) {
			numSet.add(num);
		}
		
		// 最长序列长度
		int longest = 0;
		
		// 遍历numSet,查找最长连续序列
		for (int num : numSet) {
			// 仅当num-1不存在numSet中,才认定num是个最长序列的起点
			if ( !numSet.contains(num - 1)) {
				// 当前长度和当前currentNum
				int length = 1;
				int currentNum = num + 1;
				
				// 查找numSet中currentNum的下一值
				while ( numSet.contains(currentNum) ) {
					length++;
					currentNum++;
				}
				
				// 更新最长序列长度
				longest = longest > length ? longest : length;
			}
		}
		
		// 返回最长序列长度
		return longest;	
    }
}

二、双指针

(一)移动零

思路:采用双指针法求解,i记录非零下标,j遍历数组nums,移动非零元素,j遍历完之后,i及之后的元素均为0。

时间复杂度:O(N)

空间复杂度:O(1)

class Solution {
    public void moveZeroes(int[] nums) {
        // 双指针法求解 时间复杂度O(N) 空间复杂度O(1)

        // i记录非零元素的下标
        int i = 0;

        // 遍历nums
        for (int j = 0; j < nums.length; j++) {
            if (nums[j] != 0) {
                nums[i] = nums[j];
                i++;
            }
        }

        // >=i之后的元素设置为0
        for (int j = i; j < nums.length; j++) {
            nums[j] = 0;
        } 
    }
}

(二)盛最多水的容器

思路一:常规解法,采用双层循环。

时间复杂度:O(N^2)

空间复杂度:O(1)

实现代码:

class Solution {
    public int maxArea(int[] height) {
		// 双层循环解法
		// 时间复杂度 O(N^2)
		// 空间复杂度 O(1)
		
		//  maxArea表示容器的最大水量
		int maxArea = 0;
		
		// 外层循环遍历height
		for (int i = 0; i < height.length-1; i++) {
			// 记录当前的容器水量
			int currentArea = 0;
			
			// 内层循环 寻找盛最多水的下标
			for (int j = i+1; j < height.length; j++) {
				// 容器长度:j - i
				int length = j - i;
				// 容器宽度:Math.min(height[i], height[j])
				int width = height[i] > height[j] ? height[j] : height[i];
				currentArea = length * width;
				maxArea = maxArea > currentArea ? maxArea : currentArea;
			}
		}
		
		// 返回容器的最大水量
		return maxArea;
    }
}

思路二:双指针法。

时间复杂度:O(N)

空间复杂度:O(1)

实现代码:

class Solution {
    public int maxArea(int[] height) {
		// 双指针解法 容器面积:(j - i) * (Math.min(height[i], height[j]))
		// 时间复杂度:O(N)
		// 空间复杂度:O(1)
		
		int i = 0, j = height.length-1;
		
		// 容器最大水量
		int maxArea = 0;
		
		// 寻找容器最大水量
		while (i < j ) {
			// 记录当前的容器水量
			int currentArea = ( j - i ) * ( height[i] > height[j] ? height[j] : height[i] );
			
			// 更新容器最大水量
			maxArea = maxArea > currentArea ? maxArea : currentArea;
			
			// 指针移动判断,谁小移动谁
			if ( height[i] < height[j] ) {
				i++;
			} else {
				j--;
			}
		}
		
		// 返回容器的最大水量
		return maxArea;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值