LeetCode算法题

第1题https://leetcode-cn.com/problems/two-sum/node

两数之和算法

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。数组

你能够假设每种输入只会对应一个答案。可是,你不能重复利用这个数组中一样的元素。优化

示例:spa

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

由于 nums[0] + nums[1] = 2 + 7 = 9
因此返回 [0, 1]blog

常规算法排序

public class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        res:
        for (int i = 0;i < nums.length;i++) {
            for (int j = i + 1;j < nums.length;j++) {
                if (nums[i] + nums[j] == target) {
                    result[0] = i;
                    result[1] = j;
                    break res;
                }
            }
        }
        return result;
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] a = {2,7,11,15};
        int[] result = solution.twoSum(a,9);
        for (int i = 0;i < result.length;i++) {
            System.out.println(result[i]);
        }
    }
}

运行结果leetcode

0
1rem

但该算法的时间复杂度为O(n^2)的,因此咱们考虑将该算法下降到O(n)级别

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

    public static void main(String[] args) {
        Solution1 solution = new Solution1();
        int[] a = {2,7,11,15};
        int[] result = solution.twoSum(a,9);
        for (int i = 0;i < result.length;i++) {
            System.out.println(result[i]);
        }
    }
}

运行结果

0
1

第2题https://leetcode-cn.com/problems/add-two-numbers/

两数相加

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

若是,咱们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您能够假设除了数字 0 以外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
缘由:342 + 465 = 807

正面刚

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        String a = "";
        while (l1 != null) {
            a += l1.val;
            l1 = l1.next;
        }
        a = new StringBuffer(a).reverse().toString();
        String b = "";
        while (l2 != null) {
            b += l2.val;
            l2 = l2.next;
        }
        b = new StringBuffer(b).reverse().toString();
        String result = "";
        boolean add = false;
        int d = 0;
        int len;
        if (a.length() < b.length()) {
            len = b.length();
        }else {
            len = a.length();
        }
        for (int i = 0;i < len;i++) {
            if (add) {
                if (i < a.length() && i < b.length()) {
                    d = Integer.parseInt(a.substring(a.length() - 1 - i, a.length() - i))
                            + Integer.parseInt(b.substring(b.length() - 1 - i, b.length() - i)) + 1;
                }else if (i >= a.length()) {
                    d = Integer.parseInt(b.substring(b.length() - 1 - i, b.length() - i)) + 1;
                }else if (i >= b.length()) {
                    d = Integer.parseInt(a.substring(a.length() - 1 - i, a.length() - i)) + 1;
                }
            }else {
                if (i < a.length() && i < b.length()) {
                    d = Integer.parseInt(a.substring(a.length() - 1 - i, a.length() - i))
                            + Integer.parseInt(b.substring(b.length() - 1 - i, b.length() - i));
                }else if (i >= a.length()) {
                    d = Integer.parseInt(b.substring(b.length() - 1 - i, b.length() - i));
                }else if (i >= b.length()) {
                    d = Integer.parseInt(a.substring(a.length() - 1 - i, a.length() - i));
                }
            }
            if (d >= 10) {
                result += String.valueOf(d).substring(1,2);
                add = true;
            }else {
                result += String.valueOf(d);
                add = false;
            }
        }
        if (add) {
            result += 1;
        }
        ListNode node = new ListNode(Integer.parseInt(result.substring(0,1)));
        ListNode ret = node;
        for (int i = 1;i < result.length();i++) {
            node.next = new ListNode(Integer.parseInt(result.substring(i,i + 1)));
            node = node.next;
        }
        return ret;
    }
}

第2题的优化

根据上面比较复杂的写法,根据其原理作了极简优化

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        boolean add = false;
        ListNode dummyHead = new ListNode(-1);
        ListNode node = dummyHead;
        while (l1 != null && l2 != null) {
            int sum;
            if (add) {
                sum = l1.val + l2.val + 1;
            }else {
                sum = l1.val + l2.val;
            }
            if (sum >= 10) {
                add = true;
            }else {
                add = false;
            }
            node.next = new ListNode(sum % 10);
            node = node.next;
            l1 = l1.next;
            l2 = l2.next;
        }
        while (l1 != null) {
            if (add) {
                node.next = new ListNode((l1.val + 1) % 10);
                if (l1.val + 1 >= 10) {
                    add = true;
                }else {
                    add = false;
                }
            }else {
                node.next = new ListNode(l1.val);
            }
            node = node.next;
            l1 = l1.next;
        }
        while (l2 != null) {
            if (add) {
                node.next = new ListNode((l2.val + 1) % 10);
                if (l2.val + 1 >= 10) {
                    add = true;
                }else {
                    add = false;
                }
            }else {
                node.next = new ListNode(l2.val);
            }
            node = node.next;
            l2 = l2.next;
        }
        if (add) {
            node.next = new ListNode(1);
        }
        return dummyHead.next;
    }
}

晒一下成绩

第3题https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: "abcabcbb"
输出: 3 
解释: 由于无重复字符的最长子串是 长度为 3。"abc",因此其

示例 2:

输入: "bbbbb"
输出: 1
解释: 由于无重复字符的最长子串是 ,因此其长度为 1。"b"

示例 3:

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

这道题使用暴力解题是会超时的。比方说这样

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        Map<Set<Character>,Integer> map = new HashMap<>();
        Set<Character> key = new HashSet<>();
        int from = 0;
        String s1 = s;
        while (!s.equals("")) {
            for (int i = 0; i < s.length(); i++) {
                if (!key.contains(s.charAt(i))) {
                    key.add(s.charAt(i));
                    map.put(key, key.size());
                } else {
                    map.put(key, key.size());
                    key.clear();
                    key.add(s.charAt(i));
                }
            }
            from++;
            s = s1.substring(from);
            key.clear();
        }
        return map.values().stream().max(Comparator.comparing(x -> x)).orElse(0);
    }
}

滑动窗口法:使用一个带边界的集合来不断调整边界范围来获取咱们须要的结果

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

第4题https://leetcode-cn.com/problems/median-of-two-sorted-arrays/

4. 寻找两个有序数组的中位数

给定两个大小为 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

以前我觉得这道题是不容许重复值的

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        SortedSet<Integer> set = new TreeSet<>();
        SortedMap<Integer,Integer> map = new TreeMap<>();
        double ret;
        for (int i = 0;i < nums1.length;i++) {
            set.add(nums1[i]);
        }
        for (int i = 0;i < nums2.length;i++) {
            set.add(nums2[i]);
        }
        int len = set.size();
        for (int i = 1;i <= len;i++) {
            map.put(i,set.first());
            set.remove(set.first());
        }
        if ((map.size() & 1) == 0) {
            if (map.size() > 2) {
                SortedMap<Integer, Integer> subMap = map.subMap(map.size() / 2, map.size() / 2 + 2);
                ret = (subMap.get(subMap.firstKey()) + subMap.get(subMap.lastKey())) / 2.0;
            }else {
                ret = (map.get(map.firstKey()) + map.get(map.lastKey())) / 2.0;
            }
        }else {
            if (map.size() > 1) {
                SortedMap<Integer, Integer> subMap = map.subMap(map.size() / 2 + 1, map.size() / 2 + 2);
                ret = subMap.get(subMap.firstKey());
            }else {
                ret = map.get(map.firstKey());
            }
        }
        return ret;
    }
}

可是提交给leetCode是不能经过的,实际上它容许重复值。

如今改用归并排序,结果能够经过了,但实际上在归并排序中的时间复杂度为O(m+n),并不能知足时间复杂度的要求

class Solution1 {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int i = 0;
        int j = 0;
        int[] data = new int[nums1.length + nums2.length];
        for (int k = 0;k < data.length;k++) {
            if (i >= nums1.length) {
                data[k] = nums2[j];
                j++;
            }else if (j >= nums2.length) {
                data[k] = nums1[i];
                i++;
            }else if (nums1[i] < nums2[j]) {
                data[k] = nums1[i];
                i++;
            }else {
                data[k] = nums2[j];
                j++;
            }
        }
        if ((data.length & 1) == 1) {
            return data[data.length / 2];
        }else {
            return (data[data.length / 2 - 1] + data[data.length / 2]) / 2.0;
        }
    }
}

以后咱们会改用二分查找法才能真正知足算法复杂度的要求。

相关文章
相关标签/搜索