leetcode解题记录

Practice 1:

题目描述:

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

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

示例:

给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

我的解答:

 1 class Solution {
 2    public int[] twoSum(int[] nums, int target) {
 3         int [] array = nums;
 4         int sum = target;
 5         int second;
 6         int first;
 7         for (int i = 0; i < array.length; i++) {
 8             first = array[i];
 9             second = sum - first;
10             for (int j = i+1; j <array.length ; j++) {
11                 if (second == array[j]){
12                     return new int[] {i,j};
13                 }
14             }
15         }
16         return null;
17     } 
18 }

更优解答案解析:

两遍哈希表

 1 public int[] twoSum(int[] nums, int target) {
 2     Map<Integer, Integer> map = new HashMap<>();
 3     for (int i = 0; i < nums.length; i++) {
 4         map.put(nums[i], i);
 5     }
 6     for (int i = 0; i < nums.length; i++) {
 7         int complement = target - nums[i];
 8         if (map.containsKey(complement) && map.get(complement) != i) {
 9             return new int[] { i, map.get(complement) };
10         }
11     }
12     throw new IllegalArgumentException("No two sum solution");
13 }
  • 时间复杂度:O(n), 我们把包含有 nn 个元素的列表遍历两次。由于哈希表将查找时间缩短到 O(1)) ,所以时间复杂度为 O(n)

  • 空间复杂度:O(n), 所需的额外空间取决于哈希表中存储的元素数量,该表中存储了 n 个元素。 

 

Practice 2:

给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。

你可以假设除了数字 0 之外,这两个数字都不会以零开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)

输出:7 -> 0 -> 8

原因:342 + 465 = 807

我的解答:

这道题自己没有做出来,在看完解答后,按答案的方式做了一遍。

 1 /**
 2  * Definition for singly-linked list.
 3  * public class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode(int x) { val = x; }
 7  * }
 8  */
 9 class Solution {
10      public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
11          ListNode head = new ListNode(0);
12          ListNode curr = head;
13          ListNode p = l1;
14          ListNode q = l2;
15          int carry = 0;
16          int sum = 0;
17         while (p != null || q != null) {
18             int x = (p!=null)?p.val:0;
19             int y = (q!=null)?q.val:0;
20             sum = x+y+carry;
21             carry = sum/10;
22             curr.next = new ListNode(sum%10);
23             curr = curr.next;
24             if(p!=null)
25                 p=p.next;
26             if(q!=null)
27                 q=q.next;
28 
29         }
30          if(carry>0){
31              curr.next = new ListNode(1);
32          }
33          
34     
35         return head.next;
36     }
37 }

 

Practice 3

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

示例:

给定 "abcabcbb" ,没有重复字符的最长子串是 "abc" ,那么长度就是3。

给定 "bbbbb" ,最长的子串就是 "b" ,长度是1。

给定 "pwwkew" ,最长子串是 "wke" ,长度是3。请注意答案必须是一个子串,"pwke" 是 子序列  而不是子串。

我的解答错误

答案解析:

(一)暴力法

逐个检查所有的子字符串,看它是否不含有重复的字符。

 1 public class Solution {
 2     public int lengthOfLongestSubstring(String s) {
 3         int n = s.length();
 4         int ans = 0;
 5         for (int i = 0; i < n; i++)
 6             for (int j = i + 1; j <= n; j++)
 7                 if (allUnique(s, i, j)) ans = Math.max(ans, j - i);
 8         return ans;
 9     }
10 
11     public boolean allUnique(String s, int start, int end) {
12         Set<Character> set = new HashSet<>();
13         for (int i = start; i < end; i++) {
14             Character ch = s.charAt(i);
15             if (set.contains(ch)) return false;
16             set.add(ch);
17         }
18         return true;
19     }
20 }

(二)滑动窗口

 滑动窗口是数组/字符串问题中常用的抽象概念。 窗口通常是在数组/字符串中由开始和结束索引定义的一系列元素的集合,即 [i, j)左闭,右开)。而滑动窗口是可以将两个边界向某一方向“滑动”的窗口。例如,我们将 [i, j)向右滑动 1个元素,则它将变为 [i+1, j+1)(左闭,右开)。

使用 HashSet 将字符存储在当前窗口 [i, j)(最初 j = i)中。 然后我们向右侧滑动索引 j,如果它不在 HashSet 中,我们会继续滑动 j。直到 s[j] 已经存在于 HashSet 中。此时,我们找到的没有重复字符的最长子字符串将会以索引 i 开头。如果我们对所有的 i 这样做,就可以得到答案。

 1 public class Solution {
 2     public int lengthOfLongestSubstring(String s) {
 3         int n = s.length();
 4         Set<Character> set = new HashSet<>();
 5         int ans = 0, i = 0, j = 0;
 6         while (i < n && j < n) {
 7             // try to extend the range [i, j]
 8             if (!set.contains(s.charAt(j))){
 9                 set.add(s.charAt(j++));
10                 ans = Math.max(ans, j - i);
11             }
12             else {
13                 set.remove(s.charAt(i++));
14             }
15         }
16         return ans;
17     }
18 }

优化滑动窗口

 1 public class Solution {
 2     public int lengthOfLongestSubstring(String s) {
 3         int n = s.length(), ans = 0;
 4         Map<Character, Integer> map = new HashMap<>(); // current index of character
 5         // try to extend the range [i, j]
 6         for (int j = 0, i = 0; j < n; j++) {
 7             if (map.containsKey(s.charAt(j))) {
 8                 i = Math.max(map.get(s.charAt(j)), i);
 9             }
10             ans = Math.max(ans, j - i + 1);
11             map.put(s.charAt(j), j + 1);
12         }
13         return ans;
14     }
15 }

 执行用时最短解法

class Solution {
    public int lengthOfLongestSubstring(String s) {
        if (s ==null || s.length() <1) return 0;
        int ret =0;
        char[] sAry = s.toCharArray();
        int[] pos = new int[256];
        
        for (int i=0, j=0; j <sAry.length; j++){
            i = Math.max(pos[sAry[j]] , i);
            ret = Math.max(ret, j-i+1);
            pos[sAry[j]] = j+1;
        }
        
        return ret;
    }
}

 Practice 4

题目描述

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 。

请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n)) 。

我的解答 执行时间208ms

 1 class Solution {
 2     public double findMedianSortedArrays(int[] nums1, int[] nums2) {
 3         int[] array=twoToOne(nums1,nums2);
 4         int n = array.length;
 5         if(n%2==1){
 6             return array[n/2];
 7         }else{
 8             return ((double)array[n/2-1]+(double)array[n/2])/2;
 9         }
10         
11     }
12     
13     public int[] twoToOne(int[] nums1,int[] nums2){
14         int m = nums1.length;
15         int n=nums2.length;
16         int[] array=new int[m+n];
17         int k=0;
18         for(int i=0;i<m;i++){
19            array[k++]=nums1[i];
20         }
21         for(int j=0;j<n;j++){
22             array[k++]=nums2[j];
23         }
24         
25         return sort(array);
26         
27     }
28     
29     public int[] sort(int[] array){
30         int[] ary = array;
31         int n = ary.length;
32         for(int i = 0;i<n;i++){
33             for(int j=1;j<n-i;j++){
34                 if(ary[i]>ary[i+j]){
35                     int tmp = ary[i+j];
36                     ary[i+j]=ary[i];
37                     ary[i]=tmp;
38                     
39                 }
40             }
41         }
42         return ary;
43     }
44 }

 

答案解析

然而答案并没有弄懂

 1 class Solution {
 2     public double findMedianSortedArrays(int[] A, int[] B) {
 3         int m = A.length;
 4         int n = B.length;
 5         if (m > n) { // to ensure m<=n
 6             int[] temp = A; A = B; B = temp;
 7             int tmp = m; m = n; n = tmp;
 8         }
 9         int iMin = 0, iMax = m, halfLen = (m + n + 1) / 2;
10         while (iMin <= iMax) {
11             int i = (iMin + iMax) / 2;
12             int j = halfLen - i;
13             if (i < iMax && B[j-1] > A[i]){
14                 iMin = iMin + 1; // i is too small
15             }
16             else if (i > iMin && A[i-1] > B[j]) {
17                 iMax = iMax - 1; // i is too big
18             }
19             else { // i is perfect
20                 int maxLeft = 0;
21                 if (i == 0) { maxLeft = B[j-1]; }
22                 else if (j == 0) { maxLeft = A[i-1]; }
23                 else { maxLeft = Math.max(A[i-1], B[j-1]); }
24                 if ( (m + n) % 2 == 1 ) { return maxLeft; }
25 
26                 int minRight = 0;
27                 if (i == m) { minRight = B[j]; }
28                 else if (j == n) { minRight = A[i]; }
29                 else { minRight = Math.min(B[j], A[i]); }
30 
31                 return (maxLeft + minRight) / 2.0;
32             }
33         }
34         return 0.0;
35     }
36 }

 执行时间为38ms的代码范例

 1 class Solution {
 2     public double findMedianSortedArrays(int[] nums1, int[] nums2) {
 3         
 4            int n = nums1.length;
 5            int m = nums2.length;
 6            double re = 0;
 7            int t1=0;
 8            int t2=0;
 9            int p1=0;
10            int p2=0;
11            if((n+m)%2 == 1){
12                for(int i = 0; i< (n+m)/2 + 1; i++){
13                     if(p1<n && p2<m){
14                         if(nums1[p1] > nums2[p2]){
15                             t1 = nums2[p2];
16                             p2++;
17                         }else {
18                             t1 = nums1[p1];
19                             p1++;
20                         }
21                     }
22                    else  if(p1<n ){
23                            t1 = nums1[p1];
24                            p1++;
25                        }
26                        else if(p2<m ){
27                           t1 = nums2[p2];
28                           p2++;
29                }
30                }
31                return t1*1.0;
32            }
33            else {
34                for(int i = 0; i< (n+m)/2; i++){
35                    if(p1<n && p2<m){
36                        if(nums1[p1] > nums2[p2]){
37                            t1 = nums2[p2];
38                            p2++;
39                        }else {
40                            t1 = nums1[p1];
41                            p1++;
42                        }
43                    }
44                    else  if(p1<n ){
45                        t1 = nums1[p1];
46                        p1++;
47                    }
48                    else if(p2<m ){
49                        t1 = nums2[p2];
50                        p2++;
51                    }
52                }
53                if(p1<n && p2<m){
54                    if(nums1[p1] > nums2[p2]){
55                        t2 = nums2[p2];
56                        p2++;
57                    }else {
58                        t2 = nums1[p1];
59                        p1++;
60                    }
61                }
62                else  if(p1<n ){
63                    t2 = nums1[p1];
64                    p1++;
65                }
66                else if(p2<m ){
67                    t2 = nums2[p2];
68                    p2++;
69                }
70                return (t1+t2)/2.0;
71 
72            }
73     
74         
75     }
76 }

 Practice 5

题目描述

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。

我的解答:

 1 class Solution {
 2     public String longestPalindrome(String s) {
 3         //find all sub string 
 4         String  result=null;
 5         if(s==""){
 6             return "can not be empty.";
 7         }
 8         
 9         char[] str = s.toCharArray();
10         int n = str.length;
11         if(n==1){
12             return s;
13         }
14         int len = 1;
15         for(int i=0;i<n;i++){
16             StringBuilder sBuilder = new StringBuilder(); 
17             sBuilder.append(str[i]);
18             
19             for(int j=i+1;j<n;j++){
20                 sBuilder.append(str[j]);
21                 String tmp =sBuilder.toString();
22                 if(isPalindrome(tmp)){
23                     if(tmp.length()>=len){
24                         len = tmp.length();
25                         result=tmp;
26                     }
27                 }
28             }
29         }
30         
31         if(result==null){
32             return String.valueOf(str[0]);
33         }else{
34             return result;
35         }
36     }
37     
38     public boolean isPalindrome(String s){
39         char[] str= s.toCharArray();
40         int n = str.length;
41         for(int i=0;i<n/2;i++){
42             if(str[i]!=str[n-i-1]){
43                 return false;
44             }
45         }
46         return true;
47     }
48 }

提交后测试用例通过79个,第80个超出时间限制。

答案解析:

中心扩展算法

回文中心的两侧互为镜像。因此,回文可以从它的中心展开,并且只有 2n - 1 个这样的中心。

你可能会问,为什么会是 2n - 1 个,而不是 nn 个中心?原因在于所含字母数为偶数的回文的中心可以处于两字母之间

例如“abba”的中心在两个‘b’之间。

 1 public String longestPalindrome(String s) {
 2     int start = 0, end = 0;
 3     for (int i = 0; i < s.length(); i++) {
 4         int len1 = expandAroundCenter(s, i, i);
 5         int len2 = expandAroundCenter(s, i, i + 1);
 6         int len = Math.max(len1, len2);
 7         if (len > end - start) {
 8             start = i - (len - 1) / 2;
 9             end = i + len / 2;
10         }
11     }
12     return s.substring(start, end + 1);
13 }
14 
15 private int expandAroundCenter(String s, int left, int right) {
16     int L = left, R = right;
17     while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
18         L--;
19         R++;
20     }
21     return R - L - 1;
22 }

 

 

posted @ 2018-07-04 19:46  苏小五  阅读(162)  评论(0编辑  收藏  举报