LeetCode Hot 100~Day1

目录

两数之和

两数相加

无重复字符的最长子串 

最长回文子串 

盛最多水的容器 

删除链表的倒数第n个节点 

合并两个有序链表 

有效的括号 


两数之和

题目链接:1.两数之和

 

示例 

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

解题思路

利用hashmap将数组的值和下标以键值对的形式存储起来,遍历数组,边遍历边判断,一旦遇到符合题意的条件时,直接返回结果。每次判断map中是否存在键为target-nums[i]的键值对,如果有,则返回该键对应的值和当前的i;如果没有就将nums[i]和i存入map中。

具体代码

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            if (map.containsKey(target - nums[i])) {
                return new int[]{map.get(target - nums[i]), i};
            }
            map.put(nums[i], i);
        }
        return new int[0];
    }
}

两数相加

题目链接:2.两数相加

 

示例 

 

输入:l1 = [2,4,3], l2 = [5,6,4]

输出:[7,0,8]

说明:342 + 465 = 807.

解题思路 

该问题的核心是处理进位问题,首先定义一个进位值,每个位相加后更新进位值。同时遍历两个链表,依次相加其每一位,当有一个链表为空时,则只处理非空的链表和进位值即可

具体代码 

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode ret = new ListNode(0);
        ListNode cur = ret;
        int isAdd = 0;
        while (l1 != null && l2 != null) {
            int num = l1.val + l2.val + isAdd;
            isAdd = num / 10;
            num %= 10;
            cur.next = new ListNode(num);
            cur = cur.next;
            l1 = l1.next;
            l2 = l2.next;
        }
        ListNode l = l2 == null ? l1 : l2;
        while (l != null) {
            int num = l.val + isAdd;
            isAdd = num / 10;
            num %= 10;
            cur.next = new ListNode(num);
            cur = cur.next;
            l = l.next;
        }
        if (isAdd == 1) {
            cur.next = new ListNode(isAdd);
        }
        return ret.next;
    }
}

无重复字符的最长子串 

题目链接:3.无重复字符的最长子串

 示例

输入: s = "abcabcbb"

输出: 3

解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

解题思路

利用滑动窗口的思想可以解决该问题,遍历字符串,如果窗口内未出现重复字符,则扩大窗口的大小,右边界一直右移,如果出现了重复字符,则缩小窗口的大小,左边界右移。使用HashSet来存储每个字符,如果出现了重复的,就将窗口左边界右移,边移动边更新最大值,最终即可得到结果

class Solution {
    public int lengthOfLongestSubstring(String s) {
        Set<Character> set = new HashSet<>();
        int ret = 0;
        int r = -1;
        int n = s.length();
        for (int i = 0; i < n; i++) {
            if (i != 0) {
                set.remove(s.charAt(i - 1));
            }
            while (r + 1 < n && !set.contains(s.charAt(r + 1))) {
                set.add(s.charAt(r + 1));
                r++;
            }
            ret = Math.max(ret, r - i + 1);
        }
        return ret;
    }
}

最长回文子串 

题目链接:5.最长回文子串

 

示例

输入:s = "babad"

输出:"bab"

解释:"aba" 同样是符合题意的答案。

解题思路 

动态规划

    状态定义:f(i, j): 从i到j的字母是否为回文子串

    状态方程:f(i, j) = f(i+1, j-1) 且 (s(i) == s(j))

    初始化:f(i, i) = true f(i, i+1) = (s(i) == s(i+1))

    返回值:p(i, j) == ture中j-i+1最长的那个串

具体代码

class Solution {
    /**
    状态定义:f(i, j): 从i到j的字母是否为回文子串
    状态方程:f(i, j) = f(i+1, j-1) 且 (s(i) == s(j))
    初始化:f(i, i) = true f(i, i+1) = (s(i) == s(i+1))
    返回值:p(i, j) == ture中j-i+1最长的那个串
     */
    public String longestPalindrome(String s) {
        if (s == null || s.length() == 0) {
            return s;
        }
        int len = s.length();
        int maxLen = 1;//记录最长的回文串长度
        int begin = 0;//记录最长的回文串的初始位置
        int end = 0;//记录最长的回文串的结束位置
        boolean[][] dp = new boolean[len][len];
        for (int r = 1; r < len; r++) {
            for (int l = 0; l < r; l++) {
                if (s.charAt(l) == s.charAt(r) && (r - l <= 2 || dp[l + 1][r - 1])) {
                    dp[l][r] = true;
                    if (r - l + 1 > maxLen) {
                        maxLen = r - l + 1;
                        begin = l;
                        end = r;
                    }
                }
            }
        }
        return s.substring(begin, end + 1);
    }
}

盛最多水的容器 

题目链接:11.盛最多水的容器

 

示例

 

输入:[1,8,6,2,5,4,8,3,7]
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

解题思路 

使用双指针法,初始时,l为该容器的左边界,r为容器的右边界,维护一个面积的最大值,取l的高和r的高小的那个值作为容器的高,乘以(r - l),得到的结果即为临时面积,再与维护的最大值对比,更新为大的那一个。如果此时r的高比l的高低,就r边界左移,反之l边界右移,当l >= r时循环结束,此时的ret即为最大面积。 

class Solution {
    public int maxArea(int[] height) {
        int ret = 0;
        int l = 0;
        int r = height.length - 1;
        while (l < r) {
            int area = Math.min(height[l], height[r]) * (r - l);
            ret = Math.max(area, ret);
            if (height[l] > height[r]) {
                r--;
            } else {
                l++;
            }
        }
        return ret;
    }
}

删除链表的倒数第n个节点 

题目链接:19.删除链表的倒数第n个节点

输入:head = [1,2,3,4,5], n = 2

输出:[1,2,3,5]

解题思路 

快慢指针思想,当n小于0时,直接返回原链表头结点;当n大于0时只移动快指针,当n等于0时,快慢指针一起移动,当快指针等于空或者快指针.next等于空就跳出循环;再对n进行判断,当n等于1时,说明要删除的是头结点,其他情况将慢指针的下一个指向其下一个的下一个

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        if (n < 0) {
            return head;
        }
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            if (n > 0) {
                fast = fast.next;
                n--;
            } else {
                fast = fast.next;
                slow = slow.next;
            }
        }
        if (n == 1) {
            head = head.next;
        } else {
            slow.next = slow.next.next;
        }
        return head;
    }
}

合并两个有序链表 

题目链接:21.合并两个有序链表

 

输入:l1 = [1,2,4], l2 = [1,3,4]

输出:[1,1,2,3,4,4]

解题思路 

首先两个链表一起遍历,哪个小就将哪个先加入到新链表中,循环结束后将非空的链表再加入到新链表中即可

class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode ret = new ListNode(0);
        ListNode cur = ret;
        while (list1 != null && list2 != null) {
            if (list1.val < list2.val) {
                cur.next = list1;
                cur = cur.next;
                list1 = list1.next;
            } else {
                cur.next = list2;
                cur = cur.next;
                list2 = list2.next;
            }
        }
        ListNode l = list1 == null ? list2 : list1;
        cur.next = l;
        return ret.next;
    }
}

有效的括号 

题目链接:20.有效的括号

解题思路 

 利用栈先进后出的特性可以完美解决该问题,需要注意的遍历结束后如果栈为空,说明是有效的,不为空时说明无效,另外循环时在出栈之前也要判断栈是否为空,如果为空则无效,不为空则继续判断。

class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        for (int i = 0; i < s.length(); i++) {
            char tmp = s.charAt(i);
            if (tmp == '(' || tmp == '[' || tmp == '{') {
                stack.push(tmp);
            } else {
                if (stack.isEmpty()) {
                    return false;
                }
                if (tmp == ')' && stack.peek() == '(' ||
                    tmp == ']' && stack.peek() == '[' ||
                    tmp == '}' && stack.peek() == '{') {
                        stack.pop();
                } else {
                    return false;
                }
            }
        }
        if (stack.isEmpty()) {
            return true;
        }
        return false;
    }
}

 

 

 

 

 

 

 

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Li_yizYa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值