提交 48bcd752 编写于 作者: L liu13

first commit

上级
.DS_Store
*/.DS_Store
test.java
package code;
/*
* 1. Two Sum
* 题意:返回数组中和为给定数的下标
* 难度:Easy
* 分类:Array, HashTable
* 算法:题目说明了数组中一定有解,且解唯一,所以用哈希表记录已遍历的元素即可
*/
import java.util.HashMap;
import java.util.Map;
public class lc1 {
public static void main(String[] args) {
int[] nums = {2, 7, 11, 15};
int target = 9;
int[] r = twoSum(nums,target);
System.out.println(r[0]);
System.out.println(r[1]);
}
public static int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map = new HashMap<Integer, Integer>();
int[] result = new int[2];
for (int i = 0; i <nums.length ; i++) {
if(map.containsKey(nums[i])){
result[0] = map.get(nums[i]);
result[1] = i;
return result;
}
map.put(target-nums[i],i);
}
return result;
}
}
package code;
/*
* 10. Regular Expression Matching
* 题意:正则表达式匹配
* 难度:Hard
* 分类:String, Dynamic Programming, Backtracking
* Tips:可用递归的方法,每次判断两位字符。 也可用dp方法。
*/
public class lc10 {
public static void main(String[] args) {
System.out.println(isMatch("aaa","ab*a*c*a"));
}
public static boolean isMatch(String s, String p) {
// dp[i][j] = true 表示 s[0~(i-1)],p[0~(j-1)] 匹配
boolean dp[][] = new boolean[s.length()+1][p.length()+1];
dp[0][0] = true;
//初始化dp[0][i]. dp[i][0]不用初始化,因为一定为false.
for (int i = 1; i < p.length()+1 ; i++) {
if(p.charAt(i-1)=='*')
if(i>1 && dp[0][i-2])
dp[0][i] = true;
}
for (int i = 1; i < s.length()+1 ; i++) {
for (int j = 1; j < p.length()+1 ; j++) {
if(s.charAt(i-1)==p.charAt(j-1) || p.charAt(j-1)=='.')
dp[i][j] = dp[i-1][j-1];
if (p.charAt(j-1)=='*') {
if(s.charAt(i-1)!=p.charAt(j-2) && p.charAt(j-2)!='.'){
//判断s最后一位与 * 前一位是否匹配,若不匹配,则 char* 匹配空,*表示前边字符出现0次
dp[i][j] = dp[i][j-2];
}else{
dp[i][j] = (dp[i-1][j] || dp[i-1][j-1] || dp[i][j-2]);
//dp[i-1][j] * 表示前面字符出现多次
//dp[i-1][j-1] * 表示前面字符出现一次
// dp[i][j-2] *表示前边字符出现0次,覆盖这些情况. s="ba" p="baa*"; s="a" p="ab*a*"
}
}
}
}
return dp[s.length()][p.length()];
}
}
package code;
/*
* 101. Symmetric Tree
* 题意:判断二叉树是否对称
* 难度:Easy
* 分类:Tree, DFS, BFS
* Tips:递归与非递归两种方法
* 注意:题目规定是二叉树,递归方法 left.left与right.right, left.right与right.left 进行比较
*/
import java.util.Stack;
public class lc101 {
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public boolean isSymmetric(TreeNode root) {
//非递归方法
if(root==null)
return true;
Stack<TreeNode> s = new Stack();
s.push(root.left);
s.push(root.right);
while(!s.isEmpty()){
TreeNode tn1 = s.pop(), tn2 = s.pop();
if(tn1==null||tn2==null)
if(tn1 == tn2) //都为空
continue;
else
return false;
if(tn1.val!=tn2.val)
return false;
s.push(tn1.left);
s.push(tn2.right);
s.push(tn1.right);
s.push(tn2.left);
}
return true;
}
// 递归法
public boolean isSymmetric2(TreeNode root) {
return root==null || func(root.left, root.right);
}
public static boolean func(TreeNode left, TreeNode right){
if(left==null || right==null)
return left == right;
return (left.val==right.val) && func(left.left,right.right) && func(left.right,right.left);
}
}
package code;
/*
* 11. Container With Most Water
* 题意:数组下标代表横坐标,数组中的值代表纵坐标,求最大面积
* 难度:Medium
* 分类:Array, Two Pointers
* Tips:复杂度可以为O(N), 指针往里走, 若值也小了,则面积一定不会增大
*/
public class lc11 {
public static void main(String[] args) {
int[] arr = {1,8,6,2,5,4,8,3,7};
System.out.println(maxArea(arr));
}
public static int maxArea(int[] height) {
int left = 0;
int right = height.length-1;
int result = 0;
while(left<right){
result = Math.max( result, Math.min(height[left],height[right])*(right-left) );
if(height[left]<height[right])
left++;
else
right--;
}
return result;
}
}
package code;
/*
* 13. Roman to Integer
* 题意:罗马数字转Int
* 难度:Easy
* 分类:Math, String
* 注意:如何解决6种反例,两种方式: (1)判断该位置上与下一位置上大小,决定加减. (2)如何字符串中包含该情况,减去误差
*/
public class lc13 {
public static void main(String[] args) {
String s = "IV";
System.out.println(romanToInt(s));
}
public static int romanToInt(String s) {
int sum =0;
for (int i = 0; i <s.length(); i++) {
if(s.charAt(i)=='I')
sum += 1;
else if(s.charAt(i)=='V')
sum += 5;
else if(s.charAt(i)=='X')
sum += 10;
else if(s.charAt(i)=='L')
sum += 50;
else if(s.charAt(i)=='C')
sum += 100;
else if(s.charAt(i)=='D')
sum += 500;
else if(s.charAt(i)=='M')
sum += 1000;
}
if(s.contains("IV"))
sum -= 2;
if(s.contains("IX"))
sum -= 2;
if(s.contains("XL"))
sum -= 20;
if(s.contains("XC"))
sum -= 20;
if(s.contains("CD"))
sum -= 200;
if(s.contains("CM"))
sum -= 200;
return sum;
}
}
package code;
/*
* 14. Longest Common Prefix
* 题意:找最长匹配前缀
* 难度:Easy
* 分类:String
* Tips:可先将字符串排序,之后只比较数组中首和尾字符串即可
*/
import java.util.Arrays;
public class lc14 {
public static void main(String[] args) {
}
public static String longestCommonPrefix(String[] strs) {
if(strs.length==0)
return "";
Arrays.sort(strs);
char[] str1 = strs[0].toCharArray();
char[] str2 = strs[strs.length-1].toCharArray();
int len = Math.min(str1.length,str2.length);
int i = 0;
while(i<len){
if(str1[i] == str2[i])
i++;
else
break;
}
return strs[0].substring(0,i);
}
}
package code;
/*
* 15. 3Sum
* 题意:找出数组中所有和为0的三元组合
* 难度:Medium
* 分类:Array, Two Pointers
* 注意:如何避免 List 重复元素
*/
import java.util.*;
public class lc15 {
public static void main(String[] args) {
int[] nums = {-1, 0, 1, 2, -1, -4};
System.out.println(threeSum(nums).toString());
}
public static List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList();
Arrays.sort(nums);
for (int i = 0; i < nums.length-2 ; i++) {
if( i>0 && nums[i]==nums[i-1] ) //防止重复添加相同内容List
continue;
int left = i+1, right = nums.length-1;
while(left<right){
if( nums[i]+nums[left]+nums[right] == 0 ){
result.add(Arrays.asList(nums[i],nums[left],nums[right])); //Arrays.asList(int a, int b, intc);
while(left<right && nums[left]==nums[left+1]) //防止重复添加相同内容List
left++;
while(left<right && nums[right]==nums[right-1]) //防止重复添加相同内容List
right--;
left++;
right--;
}else if( nums[i]+nums[left]+nums[right] < 0 )
left++;
else
right--;
}
}
return result;
}
}
package code;
/*
* 2. Add Two Numbers
* 题意:两个链表,节点上的数逆序组成一个数字,求和,返回链表
* 难度:Medium
* 分类:Linked List, Math
* 算法:两个链表一起遍历,按位加,注意进位
* Tips:不要遍历完一个链表保存为变量,求变量和再转化为链表。因为链表可能很长,变量无法保存下来;
* 注意考虑两个链表长度不一致的问题
*/
public class lc2 {
public static void main(String[] args) {
}
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int sum = 0;
ListNode result = new ListNode(0);
ListNode cur = result;
while(l1!=null || l2!=null){
if(l1!=null) {
sum += l1.val;
l1 = l1.next;
}
if(l2!=null) {
sum += l2.val;
l2 = l2.next;
}
cur.next = new ListNode(sum%10);
cur = cur.next;
sum = sum/10;
}
if(sum==1) {
cur.next = new ListNode(1);
}
return result.next;
}
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
}
package code;
/*
* 21. Merge Two Sorted Lists
* 题意:合并两个链表
* 难度:Easy
* 分类:Linked List
* Tips:可用递归的写法,代码更简洁
*/
public class lc21 {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode res = new ListNode(0);
ListNode temp = res;
while(l1!=null && l2!=null){
if(l1.val<l2.val){
temp.next = l1;
temp = temp.next;
l1 = l1.next;
}else{
temp.next = l2;
temp = temp.next;
l2 = l2.next;
}
}
if(l1!=null)
temp.next = l1;
if(l2!=null)
temp.next = l2;
return res.next;
}
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
}
package code;
/*
* 26. Remove Duplicates from Sorted Array
* 题意:移除数组中重复元素
* 难度:Easy
* 分类:Array, Two Pointers
*/
public class lc26 {
public static void main(String[] args) {
int[] nums = {0,0,1,1,1,2,2,3,3,4};
int n = removeDuplicates(nums);
for (int i = 0; i <n ; i++) {
System.out.println(nums[i]);
}
}
public static int removeDuplicates(int[] nums) {
int n = 1;
for (int i = 1; i < nums.length ; i++) {
if(nums[i]!=nums[i-1]){
nums[n] = nums[i];
n++;
}
}
return n;
}
}
package code;
/*
* 28. Implement strStr()
* 题意:找出子串在给定字符串的起始位置
* 难度:Easy
* 分类:Two Pointers, String
* Tips:注意判断子串为空的方法为needle.length()==0,不要用needle==""
*/
public class lc28 {
public static void main(String[] args) {
String haystack = "aaaaa";
String needle = "ab";
System.out.println(strStr(haystack, needle));
}
public static int strStr(String haystack, String needle) {
if(needle.length()==0)
return 0;
int cur1 = 0, cur2 = 0;
while(cur1<haystack.length()){
if(haystack.charAt(cur1)==needle.charAt(cur2)){
cur1++;
cur2++;
if(cur2==needle.length())
return cur1-cur2;
}else{
cur1++;
cur1 = cur1-cur2;
cur2 = 0;
}
}
return -1;
}
}
package code;
/*
* 3. Longest Substring Without Repeating Characters
* 题意:找出字符串中没有重复子串的最大长度
* 难度:Medium
* 分类:Hash Table, Two Pointers, String
* 算法:两个指针,记录没有重复字母的子串的首和尾
*/
import java.util.HashMap;
public class lc3 {
public static void main(String[] args) {
String s = "abba";
System.out.println(lengthOfLongestSubstring(s));
}
public static int lengthOfLongestSubstring(String s) {
HashMap<Character,Integer> hm = new HashMap<>();
int max = 0;
int j = 0;
for (int i = 0; i <s.length() ; i++) {
if(hm.containsKey(s.charAt(i))) {
j = Math.max(hm.get(s.charAt(i))+1,j);
//if input="abbabc"
//when i = 3, s.chatAt(3) == 'a' ,
//we will found last 'a' appears at index 0,
//but we should not update j from 2 ('b') to 0 ('a'),
//because here although the 'a' is in hashMap, but it appears before 'b'.
}
//i到j没有重复的字母,所以+1
//写到if外,因为可能该串本身就没有重复的字母,以及串首与串尾也要考虑
max = Math.max(i-j+1,max);
hm.put(s.charAt(i), i);
};
return max;
}
}
package code;
/*
* 38. Count and Say
* 题意:初始输出为1,后续输出为上次输出的读法,求第n次的读法
* 难度:Easy
* 分类:String
* 注意:题意很难懂,读懂题意了就简单了
*/
public class lc38 {
public static void main(String[] args) {
System.out.println(countAndSay(5));
}
public static String countAndSay(int n) {
String temp = "1";
while(n>1){
temp = Say(temp);
n--;
}
return temp;
}
public static String Say(String str){
char[] chars = str.toCharArray();
StringBuilder res = new StringBuilder();
int sum =0;
char pre = chars[0];
for (int i = 0; i < chars.length ; i++) {
if(chars[i]==pre)
sum++;
else{
res.append(sum);
res.append(pre);
sum = 1;
pre = chars[i];
}
if(i==chars.length-1){ //注意到字符末尾后要添加一次,因为不会再循环了
res.append(sum);
res.append(pre);
}
}
return res.toString();
}
}
package code;
/*
* 4. Median of Two Sorted Arrays
* 题意:两个有序数组,找出中位数,要求复杂度O(logN)
* 难度:Hard
* 分类:Array, Binary Search, Divide and Conquer
* 注意:两个数组长度可能不一样;边际问题
*/
public class lc4 {
public static void main(String[] args) {
int[] nums1 = {1,2};
int[] nums2 = {3,4};
System.out.println(findMedianSortedArrays(nums1,nums2));
}
public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
int size1 = nums1.length;
int size2 = nums2.length;
if(size1>size2)
return findMedianSortedArrays(nums2,nums1);
int low = 0;
int high = nums1.length;
while(low<=high){// <=别忘了=
int i = (low+high)/2;
int j = (size1+size2+1)/2-i; // 注意+1
if(i>0 && nums1[i-1]>nums2[j]){ //注意判断i是否越界
//need reduce i
high = i-1;
}else if(i<size1 && nums2[j-1]>nums1[i]){ //注意判断i是否越界
//need increase i
low = i+1;
}else{
//find correct i
int l,r;
if(i==0) {
//nums1 没有 l
l = nums2[j-1];
}else if(j==0){
//nums2 没有l,两个数组可能相等
l = nums1[i-1];
} else{
l = Math.max(nums1[i-1],nums2[j-1]);
}
if((size1+size2)%2==1)
return l;
if(i==size1){
//nums1 没有 r
r = nums2[j];
}else if(j==size2){
//nums2 没有 r
r = nums1[i];
}else{
r = Math.min(nums1[i],nums2[j]);
}
return (l+r)*1.0/2;
}
}
return -1;
}
}
package code;
/*
* 5. Longest Palindromic Substring
* 题意:找出给定字符串中最长的回文串
* 难度:Medium
* 分类:String, Dynamic Programming
* Tips:从后往前遍历,保证后续dp时,子情况已计算出
*/
public class lc5 {
public static void main(String[] args) {
String s = "cbbd";
System.out.println(longestPalindrome(s));
}
public static String longestPalindrome(String s) {
int n = s.length();
boolean[][] dp = new boolean[n][n];
String res = "";
for (int i = n-1; i>=0 ; i--) {
for (int j = i; j <n ; j++) {
if(s.charAt(i)==s.charAt(j)){
if((j-i)<3 || dp[i+1][j-1])
dp[i][j] = true;
if(dp[i][j] && j-i+1>res.length())
res = s.substring(i,j+1); // 起始索引,终止索引(不包括,所以+1)
}
}
}
return res;
}
}
package code;
/*
* 53. Maximum Subarray
* 题意:最大连续子序列和
* 难度:Easy
* 分类:Array, Divide and Conquer, Dynamic Programming
* 注意:分治方法如何进行merge,merge时,必须包含mid元素,因为是连续子序列
*/
public class lc53 {
public static void main(String[] args) {
int[] nums = {-2,1,-3,4,-1,2,1,-5,4};
System.out.println(maxSubArray(nums));
System.out.println(maxSubArray2(nums));
}
public static int maxSubArray(int[] nums) {
// dp[i] 表示以nums[i]结尾的最大和
int[] dp = new int[nums.length];
dp[0] = nums[0];
int res = dp[0];
for (int i = 1; i <nums.length ; i++) {
dp[i] = dp[i-1]>0 ? dp[i-1]+nums[i] : nums[i];
res = Math.max(res,dp[i]);
}
return res;
}
public static int maxSubArray2(int[] nums) {
return DivideConquer(nums,0,nums.length-1);
}
public static int DivideConquer(int[] nums, int start, int end){
if(start == end)
return nums[start];
else{
int mid = (start+end)/2;
int left = DivideConquer(nums, start, mid);
int right = DivideConquer(nums, mid+1, end);
int temp = 0;
int lmax = nums[mid];
for (int i = mid; i >=start ; i--) {
temp += nums[i];
lmax = Math.max(temp,lmax);
}
temp = 0;
int rmax = nums[mid+1];
for (int i = mid+1; i <= end ; i++) {
temp += nums[i];
rmax = Math.max(temp,rmax);
}
return Math.max(Math.max(left,right),lmax+rmax);
}
}
}
package code;
/*
* 58. Length of Last Word
* 题意:最后一个单词的长度
* 难度:Easy
* 分类:String
* 注意:要考虑空字符,串首尾空格等情况
*/
public class lc58 {
public static void main(String[] args) {
System.out.println(lengthOfLastWord("aaa"));
}
public static int lengthOfLastWord(String s) {
int pointer = s.length()-1;
while(pointer>=0 && s.charAt(pointer)==' ')
pointer--;
int end = pointer;
while( pointer>=0 && s.charAt(pointer)!=' ')
pointer--;
return end-pointer;
}
}
package code;
/*
* 63. Unique Paths II
* 题意:路径数
* 难度:Medium
* 分类:Array, Dynamic Programming
* Tips:可以用一位数组减小空间复杂度
*/
public class lc63 {
public static void main(String[] args) {
int[][] arr = {
{0, 0, 0},
{0, 1, 0},
{0, 0, 0}
};
System.out.println(uniquePathsWithObstacles(arr));
}
public static int uniquePathsWithObstacles(int[][] obstacleGrid) {
int[][] m = new int[obstacleGrid.length][obstacleGrid[0].length];
for (int i = 0; i < obstacleGrid.length; i++) {
for (int j = 0; j <obstacleGrid[i].length ; j++) {
if(obstacleGrid[i][j]==1){
m[i][j] = 0;
}else if(i==0&&j==0){
m[i][j] = 1;
}else if(i==0){
m[i][j] = m[i][j-1];
}else if(j==0){
m[i][j] = m[i-1][j];
}else{
m[i][j] = m[i-1][j]+m[i][j-1];
}
}
}
return m[m.length-1][m[0].length-1];
}
}
package code;
/*
* 66. Plus One
* 题意:数组中各数字连起来表示一个整数,返回该整数+1后的数组
* 难度:Easy
* 分类:Array, Math
* 注意:考虑全为9的情况,要进位,第一位为1,其他为0
*/
public class lc66 {
public static void main(String[] args) {
int[] nums = plusOne(new int[]{8,9,9,9});
for(int i: nums)
System.out.println(i);
}
public static int[] plusOne(int[] digits) {
for (int i = digits.length-1; i >=0 ; i--) {
if(digits[i]<9) {
digits[i]++;
return digits;
}else{
//进位,下一位+1
digits[i] = 0;
}
}
// 全为9
int[] res = new int[digits.length+1];
res[0] = 1;
return res;
}
}
package code;
/*
* 69. Sqrt(x)
* 题意:返回x的平方根, int取整
* 难度:Easy
* 分类:Math, Binary Search
* 注意:返回的值是向下取整
*/
public class lc69 {
public static void main(String[] args) {
System.out.println(mySqrt(8));
}
public static int mySqrt(int x) {
int left = 1, right = x;
while(left<=right){ // 等于时继续循环,保证向下取整
int mid = (left + right)/2;
if(mid==x/mid)
return mid;
else if(mid>x/mid)
right = mid - 1;
else
left = mid + 1;
}
// 返回的是 right = mid-1 保证向下取整
return right;
}
}
package code;
/*
* 7. Reverse Integer
* 题意:反转一个整数
* 难度:Easy
* 分类:Math
* 注意:如何判断溢出
*/
public class lc7 {
public static void main(String[] args) {
System.out.println(reverse(-987));
}
public static int reverse(int x) {
int result =0;
while(x!=0){
int temp = result *10 + x%10;
if(temp/10!=result)
return 0;
result = temp;
x = x/10;
}
return result;
}
}
package code;
/*
* 70. Climbing Stairs
* 题意:上楼梯问题,一次走一步或两步
* 难度:Easy
* 分类:Dynamic Programming
*/
public class lc70 {
public static void main(String[] args) {
System.out.println(climbStairs(3));
}
public static int climbStairs(int n) {
if(n==1)
return 1;
if(n==2)
return 2;
int[] dp = new int[n];
dp[0] = 1;
dp[1] = 2;
for (int i = 2; i < n ; i++) {
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n-1];
}
}
package code;
/*
* 8. String to Integer (atoi)
* 题意:字符串转数字,按题目要求转换。(题出的不好,没什么意义)
* 难度:Medium
* 分类:Math, String
* 注意:如何判断溢出
*/
public class lc8 {
public static void main(String[] args) {
System.out.println(myAtoi(" -42"));
}
public static int myAtoi(String str) {
char[] s = str.toCharArray();
int i = 0;
int num = 0;
int sign = 1;
while( i<s.length && s[i]==' ')
i++;
if( i<s.length && s[i]=='+' ){
sign = 1;
i++;
}
else if( i<s.length && s[i]=='-' ){
sign = -1;
i++;
}
while( i<s.length && s[i]>='0' && s[i]<='9' ){
//sign 乘了两次,保证num为正,以便*10+下一位
int temp = sign * (num * 10 + Integer.parseInt(String.valueOf(s[i])));
if( sign==1 && temp/10*sign != num )
return Integer.MAX_VALUE;
else if( sign==-1 && temp/10*sign != num )
return Integer.MIN_VALUE;
num = temp * sign;
i++;
}
return sign * num;
}
}
package code;
/*
* 88. Merge Sorted Array
* 题意:归并数组
* 难度:Easy
* 分类:Array, Two Pointers
* 注意:实际上 nums1.length = m+n , 不会>m+n ,题意没说清楚. 用一个指针指向nums的末端,从后往前走
*/
public class lc88 {
public static void main(String[] args) {
int[] nums1 = {4,5,6,0,0,0};
int[] nums2 = {1,2,3};
int m = 3;
int n = 3;
merge(nums1,m,nums2,n);
for(int i:nums1)
System.out.println(i);
}
public static void merge(int[] nums1, int m, int[] nums2, int n) {
int ptr1 = m-1;
int ptr2 = n-1;
int cur = m+n-1;
while(ptr1>=0 && ptr2>=0){
if(nums1[ptr1]>nums2[ptr2]) {
nums1[cur--] = nums1[ptr1--];
}
else {
nums1[cur--] = nums2[ptr2--];
}
}
while(ptr2>=0)
nums1[cur--] = nums2[ptr2--];
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册