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