Leetcode hot100刷题记录

哈希

两数之和

package leetcode.editor.cn;

import java.util.HashMap;

class twoSum{
    //2024-05-11 10:49:42
    //两数之和
    //编号:[1]
    
    public static void main(String[] args) {
        Solution solution = new twoSum().new Solution();
        // TO TEST
    }
    //leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer,Integer> mp = new HashMap();

        for (int i = 0; i < nums.length; i++) {
            if(mp.containsKey(target - nums[i])){
                return new int[]{mp.get(target - nums[i] ), i};
            }

            mp.put(nums[i],i);
        }

        return new int[]{};
    }
}
//leetcode submit region end(Prohibit modification and deletion)

}

字母异位词

  //leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        HashMap<String,List<String>> mp = new HashMap<>();

        for (String str : strs) {//eat
            int[] count = new int[26];
            for (int i = 0; i < str.length(); i++) {
                count[str.charAt(i) - 'a']++;
            }//[1   1    1]

            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < 26; i++) {
                if(count[i] != 0){
                    sb.append((char) i + 'a');
                    sb.append(i);
                }
            }//a1e1t1

            String key = sb.toString();

            List<String> list = mp.getOrDefault(key,new ArrayList<>());
            list.add(str);
            mp.put(key,list);

        }

        return new ArrayList<List<String>>(mp.values());
    }
}
//leetcode submit region end(Prohibit modification and deletion)

}

最长连续序列

class Solution {
    public int longestConsecutive(int[] nums) {

        //定义HashSet,作为去重
        HashSet<Integer> set = new HashSet<>();

        //遍历nums,赋值给set
        for (Integer num : nums) {
            set.add(num);
        }

        //定义最终结果
        int result = 0;

        //把每个点都作为起始点遍历
        for (Integer num : set) {

            //记录每次的长度,用于和最终结果比较
            int longStream = 0;
            //while循环往后找,记录次数
            while(set.contains(num)){
                longStream++;
                num++;
            }

            //每次都记录最大长度
            result = Math.max(result,longStream);
        }

        return result;
    }
}

双指针

移动零

class Solution {
    public void moveZeroes(int[] nums) {

        if(nums.length == 0){
            return;
        }

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

        for (int i = j; i < nums.length; i++) {
            nums[i] = 0;
        }



    }
}

盛最多水的容器

class Solution {
    public int maxArea(int[] height) {
        int left = 0;
        int right = height.length - 1;
        int res = 0;

        while(left < right){
            res = height[left] < height[right]?
                    Math.max(res,(right - left) * (height[left++])):
                    Math.max(res,(right - left) * (height[right--]));
        }

        return res;
    }
}

三数之和

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        //构造二维数组
        List<List<Integer>> ans = new ArrayList<>();
        int len = nums.length;

        //极端情况(数组是空或者长度不够3个)
        if(nums == null || len < 3) return ans;

        //对数组进行排序
        Arrays.sort(nums);//[-4,-1,-1,0,1,2]

        for(int i = 0; i < len ; i++){
            //极端情况(数组均大于0)
            if(nums[i] > 0) break;

            //特殊情况-给a去重(i的值等于i-1的值)
            if(i>0 && nums[i] == nums[i-1]) continue;

            int left = i+1;
            int right = nums.length - 1;

            while(left < right){
                int sum = nums[i] + nums[left] + nums[right];

                //收获结果
                if(sum == 0){

                    //把这个包含三个值的固定列表结果放到ans中
                    ans.add(Arrays.asList(nums[i],nums[left],nums[right]));
                    //给bc处理重复元素,如[-3 1 1 1 2 2]
                    while(left < right && nums[left] == nums[left + 1]) left++;
                    while(left > right && nums[right] == nums[right - 1]) right--;

                    //继续向后查找下一组元素
                    left++;
                    right--;
                }

                else if (sum < 0) left++;
                else if (sum > 0) right--;
            }
        }

    return ans;
    }
}

滑动窗口

无重复字符的最长子串

class Solution {

    public int lengthOfLongestSubstring(String s) {
        HashMap<Character, Integer> mp = new HashMap<>();
        int res = 0;
        int left = 0;
        
        for (int right = 0; right < s.length(); right++) {
            if (mp.containsKey(s.charAt(right))) {
                left = Math.max(left,mp.get(s.charAt(right)) + 1);
            }
            mp.put(s.charAt(right), right);
            res = Math.max(res, right - left + 1);
        }
        
        return res;
    }
}

找到字符串中所有字母移位词

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
 List<Integer> list = new ArrayList<>();
        //极端情况判断
        if(s.length() < p.length()) return list;

        int plen = p.length();
        int slen = s.length();

        //创建两个数组作为次数的记录
        int[] scount = new int[26];
        int[] pcount = new int[26];

        //只遍历前p个元素,统计次数
        for (int i = 0; i < plen; i++) {
            //统计a出现次数并++,如 a 字母中为 1  b = 2
            ++scount[s.charAt(i) - 'a'];
            ++pcount[p.charAt(i) - 'a'];
        }

        //如果完全一致代表滑块重叠,需记录
        if(Arrays.equals(scount,pcount)){
            list.add(0);
        }

        //移动滑块
        for (int i = 0; i < s.length() - plen; i++) {
            //因为向右移动滑块,所以要剔除左边第一个字母
            --scount[s.charAt(i) - 'a'];

            //右进一个字母
            ++scount[s.charAt(i+plen) - 'a'];

            if(Arrays.equals(scount,pcount)){
                list.add(i+1);
            }

        }

        return list;
    }
}

普通数组

和为K的子数组

class Solution {
    public int subarraySum(int[] nums, int k) {
        int count = 0;
        for(int end=0;end<nums.length;end++){
            int sum = 0;
            for(int start =end;start>=0;start--){
                sum += nums[start];

                if(sum == k){
                    count++;
                }
            }
        }
        
        return count;
    }
}

合并数组

//[[2,6],[1,3],[8,10],[15,18]]
if(intervals.length == 0) return new int[][]{};

//对二维数组的第一个元素进行排序
Arrays.sort(intervals, new Comparator<int[]>() {
    @Override
    public int compare(int[] o1, int[] o2) {
        return o1[0] - o2[0];
    }
});//[,[1,3][2,6],[8,10],[15,18]]

//创建一个二维数组用来存储结果
List<int[]> merged = new ArrayList<>();

for (int i = 0; i < intervals.length; i++) {
    int left = intervals[i][0];//1
    int right = intervals[i][1];//3

    if(merged.size() == 0 || merged.get(merged.size() - 1)[1] < left){
        merged.add(new int[]{left,right});
    }else {
        merged.get(merged.size() - 1)[1] = Math.max(merged.get(merged.size() - 1)[1],right);
    }
}

return merged.toArray(new int[merged.size()][]);

轮转数组

class Solution {
    public void rotate(int[] nums, int k) {

        int[] newarr = new int[nums.length];

        for(int i=0;i<nums.length;i++){
            newarr[(i+k)%nums.length] = nums[i];
        }

        System.arraycopy(newarr,0,nums,0,nums.length);
    }
}

最大子数组和

class Solution {
    public int maxSubArray(int[] nums) {
        if(nums.length == 0) return 0;

        int[] dp = new int[nums.length];

        

        dp[0] = nums[0];
        //易错点
        int MaxLength = dp[0];

        for (int i = 1; i < nums.length; i++) {
            if(dp[i-1] > 0){
                dp[i] = dp[i-1] + nums[i];
            }else {
                dp[i] = nums[i];
            }

            MaxLength = Math.max(MaxLength,dp[i]);
        }


        return MaxLength;
    }
}

除自身以外数组的乘积

class Solution {
    public int[] productExceptSelf(int[] nums) {

        int length = nums.length;
        int[] left = new int[length];
        int[] right = new int[length];

        int[] answer = new int[length];

        //计算左边的乘积
        left[0] = 1;
        for (int i = 1; i < length; i++) {
            left[i] = nums[i-1] * left[i-1];
        }

        //计算右边的乘积
        right[length - 1] = 1;
        for (int i = length - 2; i >= 0; i--) {
            right[i] = nums[i+1] * right[i+1];
        }

        for (int i = 0; i < length; i++) {
            answer[i] = left[i] * right[i];
        }


        return answer;
    }
}

矩阵

矩阵置零

class Solution {
    public void setZeroes(int[][] matrix) {
        //获取矩阵的行的个数
        int m = matrix.length;
        //获取矩阵的列的个数
        int n = matrix[0].length;

        //用数组来记录哪些行和列中包含0
        boolean[] row = new boolean[m];
        boolean[] col = new boolean[n];

        //双层循环遍历,如果是零,那么把row和col都置为true
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if(matrix[i][j] == 0){
                    row[i] = col[j] = true;
                }
            }
        }

        //再次双层循环遍历,如果row[i] 或者 col[j] 是0,那么就把matrix[i][j]置为0
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if(row[i] || col[j]){
                    matrix[i][j] = 0;
                }
            }
        }

    }
}

螺旋矩阵

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> list = new ArrayList<>();

        //极端情况判断
        if(matrix.length == 0 || matrix[0].length == 0){
            return list;
        }

        int rows = matrix.length;
        int columns = matrix[0].length;
        
        //数组用作是否跳转方向的判断
        boolean[][] visited = new boolean[rows][columns];
        int total = rows * columns;
        int row = 0;
        int column = 0;
        
        //数组用作调整方向
        int[][] directions = {{0,1},{1,0},{0,-1},{-1,0}};
        
        //基础方向是向右
        int directionIndex = 0;
        
        for (int i = 0; i < total; i++) {
            list.add(matrix[row][column]);
            visited[row][column] = true;
            
            //提前看下一行、下一列的值
            int nextRow = row + directions[directionIndex][0];
            int nextColumn = column + directions[directionIndex][1];
            
            //根据下一行下一列的值是否超过或等于边界 判断是否调整方向
            if(nextRow < 0 || nextRow >= rows || nextColumn < 0 || nextColumn >= columns || visited[nextRow][nextColumn]){
                directionIndex = (directionIndex + 1 ) % 4;
            }
            
            //向后遍历row++ column++
            row += directions[directionIndex][0];
            column += directions[directionIndex][1];

        }

        return list;
    }
}

旋转图像

class Solution {
    public void rotate(int[][] matrix) {
        int[][] matrix_new = new int[matrix.length][matrix.length];

        for(int i = 0;i<matrix.length;i++){
            for(int j = 0;j<matrix.length;j++){
                matrix_new[j][matrix.length-i-1] = matrix[i][j];
            }
        }

        for(int i =0;i<matrix.length;i++){
            for(int j = 0 ;j<matrix.length;j++){
                matrix[i][j] = matrix_new[i][j];
            }
        }
    }
}

搜索二维矩阵 II

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        for (int[] row : matrix) {
            int index = search(row,target);
            if(index >= 0){
                return true;
            }
        }
        return false;
    }

    public int search(int[] nums , int target){
        int low = 0;
        int high = nums.length - 1;
        while(low <= high){
            int mid = (high + low) / 2;
            int num = nums[mid];
            if(num == target){
                return nums[mid];
            }else if (num > target){
                high = mid - 1;
            }else
                low =  mid + 1;
        }

        return -1 ;
    }



}

链表

相交链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        HashSet<ListNode> set = new HashSet<ListNode>();

        ListNode list1 = headA;
        ListNode list2 = headB;

        while(list1 != null){
            set.add(list1);
            list1 = list1.next;
        }

        while(list2 != null){
            if(set.contains(list2)){
                return list2;
            }
            list2 = list2.next;
        }

        return null;
    }
}

反转链表

class Solution {
    public ListNode reverseList(ListNode head) {
        Stack<ListNode> stack = new Stack<ListNode>();
        ListNode list =  head;


        while(list != null){
            stack.push(list);
            list = list.next;
        }

        ListNode list2 = stack.pop();//第一个元素用来移动
        ListNode nummy = list2;//用来返回最终结果

        while(!stack.isEmpty()){
            ListNode tempNode = stack.pop();
            list2.next = tempNode;
            list2 = list2.next;
        }

        list2.next = null;
        return nummy;
    }
}

回文链表

class Solution {
    public boolean isPalindrome(ListNode head) {

        ArrayList<ListNode> nums = new ArrayList<ListNode>();

        while(head != null){
            nums.add(head);
            head = head.next;
        }

        for (int i = 0; i < nums.size(); i++) {
            if(nums.get(i).val != nums.get(nums.size() - i -1).val){
                return false;
            }
        }

        return true;
    }
}

环形链表

public class Solution {
    public boolean hasCycle(ListNode head) {
                HashSet<ListNode> set = new HashSet<>();

        while(head!=null){
            //set.add方法会返回一个布尔类型的值
            //如果添加失败,代表有重复-->有环
            if(!set.add(head)) {
                return true;
            }

            head = head.next;
        }

        return false;
    }
}

环形链表2

public class Solution {
    public ListNode detectCycle(ListNode head) {
        HashSet<ListNode> set = new HashSet<ListNode>();

        while (head != null){
            if(set.contains(head)){
                return head;
            }

            set.add(head);
            head = head.next;
        }

        return null;

    }
}

合并两个有序链表

        if(list1 == null){
            return list2;
        }
        if(list2 == null){
            return list1;
        }

        ListNode newlist = new ListNode(0);
        ListNode bak = newlist;
        // if(list1.val <= list2.val){newlist.next = list1;list1 = list1.next;}
        // if(list1.val > list2.val){newlist.next = list2;list2 = list2.next;}

        while(list1 != null && list2 != null){
            if(list1.val <= list2.val){
                bak.next = list1;
                list1 = list1.next;
            }else{
                bak.next = list2;
                list2 = list2.next;
            }
            bak = bak.next;
        }

        if(list1 !=null){
            bak.next = list1;
        }
        if(list2 != null){
            bak.next = list2;
        }
        return newlist.next;

两数相加

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        //生成一个新的链表
        ListNode pre = new ListNode(0);
        ListNode cur = pre;
        int carry = 0;//位数
        while( l1!=null || l2!=null){
            int x = l1 == null? 0: l1.val;
            int y = l2 == null? 0: l2.val;
            int sum = x + y + carry;


            carry = sum/10;//获取位
            sum = sum % 10;//获取新链表的和
            cur.next = new ListNode(sum);//把新链表的和放到新的链表中


            cur = cur.next;
            if(l1 != null)
                l1 = l1.next;
            if(l2 != null)
                l2 = l2.next;
        }
        if(carry == 1){
            cur.next = new ListNode(carry);
        }

        return pre.next;
    }
}

删除链表的倒数第N个结点

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        //1.极端情况判断
        if(head == null){return null;}

        //2.关键变量声明
        //声明头节点
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode cur = dummy;

        //声明链表长度
        int length = Solution.LengthSearch(head);

        //3.循环遍历
        for (int i = 1; i < length - n + 1; i++) {
            cur = cur.next;//找到了该元素
        }

        cur.next = cur.next.next;
        return dummy.next;


}

    public static int LengthSearch(ListNode head){
        int length = 0;
        while (head != null){
            length++;
            head = head.next;
        }

        return length;
    }
}

两两交换链表中的节点

class Solution {
    public ListNode swapPairs(ListNode head) {
        if(head == null || head.next == null){
            return head;
        }

        ListNode newHead = head.next;
        head.next = swapPairs(newHead.next);
        newHead.next = head;
        return newHead;
    }
}

随机链表的复制

class Solution {
    public Node copyRandomList(Node head) {

        //1.极端情况判断
        if(head == null){
            return null;
        }

        //2.关键变量定义
        HashMap<Node,Node> map = new HashMap<Node, Node>();


        //3.循环遍历
        //内存中创建全新的Node(深拷贝)
        for(Node curr = head; curr != null;curr = curr.next){
            map.put(curr , new Node(curr.val));
        }

        for(Node curr = head; curr != null;curr = curr.next){
            map.get(curr).next = map.get(curr.next);
            map.get(curr).random = map.get(curr.random);
        }

        //4.返回结果
        return map.get(head);
    }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值