目录
两数之和
两数相加
无重复字符的最长子串
最长回文子串
盛最多水的容器
删除链表的倒数第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;
    }
}












![[附源码]Python计算机毕业设计宠物领养系统Django(程序+LW)](https://img-blog.csdnimg.cn/5f6d414d68e84478958a48d18b0fdf2b.png)





