算法练习 —— LeetCode 1-20题

一、两数之和

1.1 题目描述

给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。

你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

1.2 解题思路

有目标数,又限制是两个数之和,所以知道若一个数为nums[i],则另一个数为target-nums[i]。

借助Map的数据结构,key为nums[i],value为i。

则答案应符合i、map.get(target-nums[i])。

1.3 解法

时间复杂度为\(O(n)\)
空间复杂度为\(O(n)\)


public class Solution {

    public static int[] twoSum(int[] nums, int target) {

        Map<Integer,Integer> map = new HashMap<Integer,Integer>();
        for(int i = 0;i<nums.length;i++){
            if(map.containsKey(target-nums[i])){
                int[] result = new int[2];
                result[0] = map.get(target-nums[i]);
                result[1] = i;
                return result;
            }else{
                map.put(nums[i],i);
            }
        }

        return null;
    }

}

代码进一步简化

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 null;
    }
}

二、两数相加

2.1 题目描述

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

2.2 解题思路

思路是使用链表,定义变量sum来计算两条链表的对应节点的值,对sum%10作为新节点的值,sum/10判断是否进位。两条链表对应节点相加,若最后sum/10等于1,则新创建一个节点,放在尾部。

2.3 解法

时间复杂度为\(O(n)\)
空间复杂度为\(O(n)\)


class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(0);
        ListNode cur = dummy;
        ListNode p1 = l1,p2=l2;
        int sum = 0;
        while(p1 != null || p2 != null){
            if(p1 != null){
                sum += p1.val;
                p1 = p1.next;
            }
            if(p2 != null){
                sum += p2.val;
                p2 = p2.next;
            }
            cur.next = new ListNode(sum % 10);
            sum /= 10;
            cur = cur.next;
        }
        if(sum == 1){
            cur.next = new ListNode(1);
        }
        return dummy.next;
    }
}


三、无重复字符的最长子串

3.1 题目描述

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

3.2 解题思路

使用HashMap存储字符和位置
使用一个变量res记录当前最大无重复长度
使用一个变量i记录当前遍历的index
使用一个变量j计算当前无重复的起始值

如果当前的元素在map中已经存在了,则j在原先的重复字符的位置上往后挪一位
j = max(j,map.get(a)+1)

重新计算最大无重复字符个数
res = max(res,i-j+1)

3.3 解法

时间复杂度为\(O(n)\)
空间复杂度为\(O(n)\)


class Solution {
    public int lengthOfLongestSubstring(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }
        Map<Character, Integer> map = new HashMap<>();
        int res = 0;
        for (int i = 0, j = 0; i < s.length(); i++) {
            if (map.containsKey(s.charAt(i))) {
                j = Math.max(j, map.get(s.charAt(i)) + 1);
            }
            map.put(s.charAt(i), i);
            res = Math.max(res, i - j + 1);
        }
        return res;
    }
}


四、寻找两个有序数组的中位数

4.1 题目描述

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。

示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0

示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5

十一、寻找两个有序数组的中位数

给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器,且 n 的值至少为 2。

11.2 解题思路

11.3 解法


class Solution {
    public int maxArea(int[] height) {
        int l = 0;
        int r = height.length - 1;
        int maxArea = 0;
        while (l < r) {
            int maxHeight = height[l] < height[r] ? height[l] : height[r];
            int area = maxHeight * (r - l);
            if (area > maxArea) {
                maxArea = area;
            }
            if (height[l] < height[r]) {
                l++;
            } else {
                r--;
            }
        }
        return maxArea;
    }
}

二十、有效的括号


给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。


20.3 解法


import java.util.Stack;

/**
 * @author Michael Fang
 * @since 2019-08-08
 */
public class Solution {

    public boolean isValid(String s) {
        char[] charArray = s.toCharArray();
        Stack stack = new Stack();
        for (char c : charArray) {
            if (stack.isEmpty()) {
                stack.add(c);
                continue;
            }
            String result = String.valueOf(stack.peek()) + String.valueOf(c);
            if (result.equals("{}") || result.equals("[]") || result.equals("()")) {
                stack.pop();
            } else {
                stack.add(c);
            }
        }
        return stack.isEmpty();
    }

}


参考文档

[1]: LeetCode官网
[2]: 花花酱LeetCode

posted @ 2019-05-13 07:30  清泉白石  阅读(338)  评论(0编辑  收藏  举报