LeetCode1-5

Leetcode1:

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

题意:给定一个整数数组,返回两个数下标满足和等于一个特定的数;假设不存在相同的元素和得到的解只有一个;

例子:数组:[2, 7, 11,15],目标值为 9, 因为 nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].

思路:方法一:通过hashmap额外的存储空间---时间复杂度和空间复杂度都是O(n)

 1 private static int[] addSum1(int[] aa, int target) {
 2         Map<Integer, Integer> map = new HashMap<>();
 3         for (int i = 0; i < aa.length; i++) {
 4             map.put(aa[i], i);
 5         }
 6         for (int i = 0; i < aa.length; i++) {
 7             int complete = target - aa[i];
 8             // 如果map中包含差值 且不是当前的值
 9             if (map.containsKey(complete) && map.get(complete) != i) {
10                 return new int[]{map.get(complete), i};
11             }
12         }
13         return null;
14     }

方法二:时间复杂度高,迭代尝试

 1  // 方法1 迭代尝试 时间复杂度比较高
 2     private static int[] addSum(int[] aa, int target) {
 3         for (int i = 0; i < aa.length; i++) {
 4             for (int j = i + 1; j < aa.length; j++) {
 5                 if (aa[i] == target - aa[j]) {
 6                     return new int[]{i, j};
 7                 }
 8             }
 9         }
10         return null;
11     }

Leetcode 2 :

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

例子:输入: (2 -> 4 -> 3) + (5 -> 6 -> 4)
          输出: 7 -> 0 -> 8
          结果: 342 + 465 = 807.

题意:将链表的对应节点进行相加,计算出来的结果构成新的链表;

思路:通过新建一个链表,首节点是一个虚拟的节点,然后返回虚拟节点的后面的节点;

 1 public static ListNode addTwoNumbers1(ListNode l1, ListNode l2) {
 2         ListNode listNode = new ListNode(0);
 3         ListNode result = listNode;
 4         ListNode p1 = l1;
 5         ListNode p2 = l2;
 6         int cad = 0;
 7         while (p1 != null || p2 != null) {        
 8             int aa = (p1 == null ? 0: p1.val) +(p2 == null?0:p2.val) + cad;
 9             listNode.next = new ListNode(aa % 10);
10             cad = aa / 10;
11             listNode = listNode.next;
12             if (p1 != null) {
13                 p1 = p1.next;
14             }
15             if (p2 != null) {
16                 p2 = p2.next;
17             }
18         }
19         if (cad != 0) {
20             listNode.next = new ListNode(cad);
21         }
22 
23         return result.next;
24     }
View Code

Leetcode 3 :

Given a string, find the length of the longest substring without repeating characters.

题意:给定一个字符串,找到不含重复元素的子串的最大长度;

思路:

 1 public static int lengthOfLongestSubstring(String s) {
 2         int k = 0;
 3         int res = 0;
 4         char[] array = s.toCharArray();
 5         HashSet<Character> hashSet = new HashSet<>();
 6         for (int i = 0; i < array.length; i++) {
 7             if (!hashSet.contains(array[i])) {
 8                 // 如果set中不存在这个值 就将他加入 并更新结果值
 9                 hashSet.add(array[i]);
10                 res = Math.max(res, hashSet.size());
11             } else {
12                 // 如果存在 将重复元素的前面部分去掉 取重复元素的下一个
13                 while (k < i) {
14                     if (s.charAt(k) == array[i]) {
15                         k++;
16                         break;
17                     } else {
18                         hashSet.remove(array[k]);
19                         k++;
20                     }
21                 }
22             }
23         }
24         return res;
25     }
26 
27     public static int lengthOfLongestSubstring1(String s) {
28         int length = s.length();
29         if (length == 0) {
30             return 0;
31         }
32         int[] countTable = new int[256];
33         Arrays.fill(countTable, -1);
34         int max = 1;
35         int start = 0;
36         int end = 1;
37         countTable[s.charAt(0)] = 0;
38         while (end < length) {
39             // Has not reached a duplicate char
40             if (countTable[s.charAt(end)] >= start) {
41                 start = countTable[s.charAt(end)] + 1;
42             }
43             max = Math.max(max, end - start + 1);
44             countTable[s.charAt(end)] = end;
45             end++;
46         }
47         return max;
48     }
49 
50     public static int lengthOfLongestSubstring2(String s) {
51         int n = s.length(), ans = 0;
52         int[] index = new int[128];
53         for (int j = 0, i = 0; j < n; j++) {
54             System.out.println(s.charAt(j) + "..");
55             System.out.println(index[s.charAt(j)] + "....");
56             i = Math.max(index[s.charAt(j)], i);//返回该字符第一次重复出现的位置
57             System.out.println("i:"+i);
58             ans = Math.max(ans, j - i + 1);//返回字符的长度
59             index[s.charAt(j)] = j + 1;//记录该字符在字符串中的位置
60         }
61         return ans;
62     }
View Code

Leetcode 4 :

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

You may assume nums1 and nums2 cannot be both empty.

题意:在两个有序数组中,寻找中位数。要求运行时间在O(log (m+n)),假设连个数组都不同时为空;

思路:将两个数组排序成一个有序的数组,如果为偶数,去中间两个数的平均值;如果为奇数,直接去中间的数;

  //O(nlogn)
 1 public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
 2         int m = nums1.length;
 3         int n = nums2.length;
 4         //当两个数组都是空的时候
 5         if (m == 0 && n == 0) {
 6             return 0;
 7         }
 8         //当其中一个数组为空时
 9         if (m == 0) {
10             return getMidVal(nums2, n);
11         }
12         if (n == 0) {
13             return getMidVal(nums1, m);
14         }
15         int[] res = new int[m + n];
16         int j = 0;
17         int k = 0;
18         for (int i = 0; i < res.length; i++) {
19             //当其中一个数组为空时 另一个还未空时
20             if (j == m && k != n) {
21                 res[i] = nums2[k++];
22                 continue;
23             }
24             if (k == n && j != m) {
25                 res[i] = nums1[j++];
26                 continue;
27             }
28             //当两个都没空时
29             if (nums1[j] < nums2[k]) {
30                 res[i] = nums1[j];
31                 j++;
32             } else {
33                 res[i] = nums2[k];
34                 k++;
35             }
36         }
37         //根据奇偶数取中位数
38         return getMidVal(res, m + n);
39     }
40 
41     private static double getMidVal(int[] nums2, int n) {
42         if (n % 2 == 0) {
43             return (double) (nums2[n / 2 - 1] + nums2[n / 2]) / 2;
44         } else {
45             return nums2[n / 2];
46         }
47     }

问题转换为求两个数组中第K个小的元素.

首先假设数组A和B的元素个数都大于k/2,我们比较A[k/2-1]和B[k/2-1]两个元素,这两个元素分别表示A的第k/2小的元素和B的第k/2小的元素。这两个元素比较共有三种情况:>、<和=。如果A[k/2-1]<B[k/2-1],这表示A[0]到A[k/2-1]的元素都在A和B合并之后的前k小的元素中。换句话说,A[k/2-1]不可能大于两数组合并之后的第k小值,所以我们可以将其抛弃。

当A[k/2-1]>B[k/2-1]时存在类似的结论。

当A[k/2-1]=B[k/2-1]时,我们已经找到了第k小的数,也即这个相等的元素.

  • 如果A或者B为空,则直接返回B[k-1]或者A[k-1];
  • 如果k为1,我们只需要返回A[0]和B[0]中的较小值;
  • 如果A[k/2-1]=B[k/2-1],返回其中一个;
 1 public class Solution {
 2     public static double findKth(int a[],int begina,int m,int b[],int beginb,int n,int k){
 3         if(m>n)              //确保函数m<=n
 4             return findKth(b,beginb,n,a,begina,m,k);
 5         if(m==0)
 6             return b[beginb+k-1];
 7         if(k==1)
 8             return Math.min(a[begina],b[beginb]);
 9         int ma = Math.min(k / 2, m), mb = k - ma;  //把k分成两部分
10         if(a[begina+ma-1]<b[beginb+mb-1])        //把a数组前面ma个元素去掉,第k小的元素不在这里
11             return  findKth(a,begina+ma,m-ma,b,beginb,n,k-ma);
12         else if(a[begina+ma-1]>b[beginb+mb-1])   //把b数组前面mb个元素去掉,第k小的元素不在这里
13             return  findKth(a,begina,m,b,beginb+mb,n-mb,k-mb);
14         else return a[begina+ma-1];              //相等时就是它
15 
16     }
17     public static double findMedianSortedArrays(int A[], int B[]) {
18         int m=A.length;
19         int n=B.length;
20         int totalLength=m+n;
21         if (totalLength%2 == 1)      //奇数长度
22             return findKth(A, 0, m, B, 0, n, totalLength/2+1);
23         else {                           //偶数长
24             return (findKth(A, 0, m, B, 0, n, totalLength / 2) + findKth(A, 0, m, B, 0, n, totalLength / 2 + 1)) / 2;
25         }
26     }
27     public static void main(String[] args){
28         int[] a={3};
29         int[] b={1,2};
30         double median=findMedianSortedArrays(a,b);
31         System.out.println(median);
32 
33     }
34 }

Leetcode 5 : 最长回文子串

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

思路 动态规划

  1 // 动态规划
  2     public static String findLongestPalindrome1(String s) {
  3         if (s == null || s.length() == 0 || s.length() == 1) {
  4             return s;
  5         }
  6         int len = s.length();
  7         int start = 0;
  8         int maxlength = 0;
  9         boolean p[][] = new boolean[s.length()][s.length()];
 10         // 子串长度为1和为2的初始化
 11         for (int i = 0; i < len; i++) {
 12             p[i][i] = true;
 13             if (i < len - 1 && s.charAt(i) == s.charAt(i + 1)) {
 14                 p[i][i + 1] = true;
 15                 start = i;
 16                 maxlength = 2;
 17             }
 18         }
 19         // 使用上述结果可以dp出子串长度为3~len -1的子串
 20         for (int strlen = 3; strlen <= len; strlen++) {
 21             for (int i = 0; i <= len - strlen; i++) {
 22                 int j = i + strlen - 1; // 子串结束的位置
 23                 if (p[i + 1][j - 1] && s.charAt(i) == s.charAt(j)) {
 24                     p[i][j] = true;
 25                     maxlength = strlen;
 26                     start = i;
 27                 }
 28             }
 29         }
 30         if (maxlength > 0)
 31             return s.substring(start, start + maxlength);
 32         return new String(s.substring(0, 1));
 33     }
 34 
 35     // 中心扩展法
 36     public String longestPalindrome(String s) {
 37         if (s == null || s.length() == 0 || s.length() == 1) {
 38             return s;
 39         }
 40         int len = s.length();
 41         int maxlength = 0;
 42         int start = 0;
 43         // 类似于aba这种情况,以i为中心向两边扩展
 44         for (int i = 0; i < len; i++) {
 45             int j = i - 1;
 46             int k = i + 1;
 47             while (j >= 0 && k < len && s.charAt(j) == s.charAt(k)) {
 48                 if (k - j + 1 > maxlength) {
 49                     maxlength = k - j + 1;
 50                     start = j;
 51                 }
 52                 j--;
 53                 k++;
 54             }
 55         }
 56         // 类似于abba这种情况,以i,i+1为中心向两边扩展
 57         for (int i = 0; i < len; i++) {
 58             int j = i;
 59             int k = i + 1;
 60             while (j >= 0 && k < len && s.charAt(j) == s.charAt(k)) {
 61                 if (k - j + 1 > maxlength) {
 62                     maxlength = k - j + 1;
 63                     start = j;
 64                 }
 65                 j--;
 66                 k++;
 67             }
 68         }
 69         if (maxlength > 0)
 70             return s.substring(start, start + maxlength);
 71         return new String(s.substring(0, 1));
 72     }
 73 
 74     // Manacher算法
 75     public static String findLongestPalindrome3(String s) {
 76         if (s == null || s.length() < 1)
 77             return s;
 78         String str = dealWithS(s); // 处理一下s,即将给字符串s的中间加上特殊字符,这样无论对于奇数字符还是偶数字符可以做同样的处理
 79         int[] res = new int[str.length()];
 80         int R = 0; // 当前所能扩展的半径
 81         int C = 0; // C位置的半径为R
 82         int maxC = 0; // 最长的半径的位置
 83         res[0] = 0;
 84         for (int i = 1; i < str.length(); i++) {
 85             int j = 2 * C - i; // i点的对称点
 86             if (j >= 0 && res[j] < R - i) // 对称点存在且对称点的回文半径在C的回文中
 87             {
 88                 res[i] = res[j];
 89             } else // 否则,需要根据i点一点一点的计算
 90             {
 91                 int k = 1;
 92                 while (R + k < str.length() && 2 * i - R - k >= 0) {
 93                     if (str.charAt(R + k) == str.charAt(2 * i - R - k))
 94                         k++;
 95                     else
 96                         break;
 97                 }
 98                 res[i] = R - i + k - 1;
 99                 if (res[i] + i > R) {
100                     R = res[i] + i;
101                     C = i;
102                 }
103             }
104 
105             maxC = res[maxC] > res[i] ? maxC : i; // maxC保存的是回文半径最大的那个点的位置
106         }
107         String subStr = str.substring(maxC - res[maxC], maxC + res[maxC] + 1);
108         StringBuffer sb = new StringBuffer();
109         for (int i = 0; i < subStr.length(); i++) {
110             if (subStr.charAt(i) != '#')
111                 sb.append(subStr.charAt(i));
112         }
113         return sb.toString();
114     }
115 
116     public static String dealWithS(String s) // 将原字符串进行处理
117     {
118         StringBuffer sb = new StringBuffer();
119         sb.append("#");
120         for (int i = 0; i < s.length(); i++) {
121             sb.append(s.charAt(i));
122             sb.append("#");
123         }
124         return sb.toString();
125     }
View Code

 

posted @ 2018-09-20 20:51  bwwbww  阅读(106)  评论(0编辑  收藏  举报