編程合集: https://www.cnblogs.com/jssj/p/12002760.html
前言:不僅僅要實現,更要提升性能,精益求精,用盡量少的時間復雜度和空間復雜度解決問題。
【程序48】
給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和為目標值的那 兩個 整數,並返回他們的數組下標
import java.util.HashMap; import java.util.Map; /** * 【程序48】 * 給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和為目標值的那 兩個 整數,並返回他們的數組下標 */ public class Subject48 { public static void main(String[] args) { int[] nums = new int[]{1,4,5,6,7,9,76,43,22,11}; int target = 11; int[] result = twoSum(nums,target); for (int i = 0; i < result.length; i++) { System.out.println(result[i]); } } /** * 獲取滿足條件的數組下標 * @param nums * @param target */ private static int[] twoSum(int[] nums, int target) { int[] temp = new int[2]; Map<Integer,Integer> map = new HashMap<>(); //遍歷查找 for(int i = 0; i < nums.length; i++){ int a = nums[i]; //判斷鍵值是否存在 if(map.containsKey(target - a)){ temp[0] = map.get(target - a); temp[1] = i; return temp; }else {//如果找不到則存進去 map.put(nums[i], i); } } return null; } }
時間復雜度為 O(n)。
運行結果:
【程序49】
給出兩個非空 的鏈表用來表示兩個非負的整數。其中,它們各自的位數是按照逆序的方式存儲的,並且它們的每個節點只能存儲一位數字。
如果,我們將這兩個數相加起來,則會返回一個新的鏈表來表示它們的和。
您可以假設除了數字 0 之外,這兩個數都不會以 0開頭。
public class ListNode { int val; ListNode next; ListNode(){ } ListNode(int x) { val = x; } }
/** * 【程序49】 * 給出兩個非空 的鏈表用來表示兩個非負的整數。其中,它們各自的位數是按照逆序的方式存儲的,並且它們的每個節點只能存儲一位數字。 * 如果,我們將這兩個數相加起來,則會返回一個新的鏈表來表示它們的和。 * 您可以假設除了數字 0 之外,這兩個數都不會以 0開頭。 * * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } } */ public class Subject49 { public static void main(String[] args) { ListNode l1 = new ListNode(2); ListNode l12 = new ListNode(4); ListNode l13 = new ListNode(3); l1.next = l12; l12.next = l13; ListNode l2 = new ListNode(5); ListNode l21 = new ListNode(6); ListNode l22 = new ListNode(4); l2.next = l21; l21.next = l22; ListNode listNode = addTwoNumbers(l1,l2); StringBuilder stringBuilder = null; while(listNode !=null){ //指向位置是否為空 if(stringBuilder == null){ stringBuilder = new StringBuilder(); stringBuilder.append(listNode.val); }else{ stringBuilder.append(" -> "+ listNode.val); } listNode = listNode.next; // 指向下一個節點 } System.out.println(stringBuilder.toString()); } /** * 鏈表輸出和 * @param l1 * @param l2 * @return */ public static ListNode addTwoNumbers(ListNode l1, ListNode l2){ int carry = 0; //進位 ListNode newListNode = new ListNode(0); ListNode tmpListNode ; tmpListNode = newListNode; while(true){ ListNode listNode = new ListNode(0); int tmp = l1.val + l2.val + carry; if(tmp < 10){ listNode.val = tmp; carry = 0; }else{ listNode.val = tmp%10; carry = 1; } tmpListNode.next = listNode; tmpListNode = listNode; if(l1.next ==null && l2.next == null &&carry == 0){ break; } if(l1.next != null){ l1 = l1.next; }else{ l1 = new ListNode(0); } if( l2.next != null){ l2 = l2.next; }else{ l2 = new ListNode(0); } } return newListNode.next; } }
時間復雜度:O(\max(m, n))
運行結果:
【程序50】
給定一個字符串,請你找出其中不含有重復字符的最長子串的長度。
import java.util.ArrayList; import java.util.List; /** * 給定一個字符串,請你找出其中不含有重復字符的最長子串的長度。 */ public class Subject50 { public static void main(String[] args) { String Str = "aabcdfffwwesdwhjkl"; int count = lengthOfLongestSubstring(Str); System.out.println(count); } /** * 獲取字符最大長度 * @param s * @return */ public static int lengthOfLongestSubstring(String s) { char[] arr = s.toCharArray(); List<Character> list = new ArrayList<>(); int maxCount = 0; int count; for (int i = 0; i < arr.length; i++) { if(list.contains(arr[i])){ count = list.size(); if(count> maxCount){ maxCount = count; } for (int j = 0; j < list.size(); j++) { if(list.get(j) != arr[i]){ list.remove(j); j--; }else{ list.remove(j); break; } } list.add(arr[i]); }else{ list.add(arr[i]); } } if(list.size() > maxCount){ return list.size(); }else{ return maxCount; } } }
時間復雜度:O(n)
運行結果:
【程序51】
給定兩個大小為 m 和 n 的有序數組nums1 和nums2。
請你找出這兩個有序數組的中位數,並且要求算法的時間復雜度為O(log(m + n))。
你可以假設nums1和nums2不會同時為空
/** * 給定兩個大小為 m 和 n 的有序數組nums1 和nums2。 * 請你找出這兩個有序數組的中位數,並且要求算法的時間復雜度為O(log(m + n))。 * 你可以假設nums1和nums2不會同時為空 */ public class Subject51 { public static void main(String[] args) { int[] nums1 = new int[]{1,2,3}; int[] nums2 = new int[]{1,2}; double arr = findMedianSortedArrays(nums1,nums2); System.out.println(arr); } public static int PartSort(int arr[], int low, int high) { int data = arr[low]; /**一次遍歷的方法:插空法 定義一個data將arr[low]存起來,並把這個位置挖空*/ while (low < high) { while (low < high && arr[high] >= data) { high--; } arr[low] = arr[high]; /**從high,也就是后面往前遍歷 找到比鍵值小的數據 插入到前面留下的空中 high位再次留下空來*/ while (low < high && arr[low] <= data) { low++; } arr[high] = arr[low]; } arr[low] = data; /**循環退出后 low和high重合 將將鍵值賦給第low,並將low返回*/ return low; } /** * 快速排序法 * @param arr * @param low * @param high */ public static void quickSort(int arr[], int low, int high) { if(low<high) { //防止發生棧溢出異常 int index = PartSort(arr, low, high); quickSort(arr, low, index - 1); quickSort(arr, index + 1, high); } } /** * 尋找中位數 * @param nums1 * @param nums2 * @return */ public static double findMedianSortedArrays(int[] nums1, int[] nums2) { int a = nums1.length; int b = nums2.length; int[] arr = new int[a+b]; double result = 0.0; if(a >= 2 && b >=2 ){ if(nums1[0] <= nums1[1] && nums2[0] <= nums2[1] ){ if(nums1[0] >= nums2[0]){ for (int i = 0; i < b; i++) { arr[i] = nums2[i]; } for (int i = 0; i < a; i++) { arr[i+b] = nums1[i]; } }else{ for (int i = 0; i < a; i++) { arr[i] = nums1[i]; } for (int i = 0; i < b; i++) { arr[i+a] = nums2[i]; } } }else if(nums1[0] >= nums1[1] && nums2[0] >= nums2[1]){ if(nums1[a-1] <= nums2[b-1]){ for (int i = 0; i < a; i++) { arr[i] = nums1[a-i-1]; } for (int i = 0; i < b; i++) { arr[i+a] = nums2[b-i-1]; } }else{ for (int i = 0; i < b; i++) { arr[i] = nums1[b-i-1]; } for (int i = 0; i < a; i++) { arr[i+b] = nums2[a-i-1]; } } }else if(nums1[0] <= nums1[1] && nums2[0] >= nums2[1]){ if(nums1[0] <= nums2[b-1]){ for (int i = 0; i < a; i++) { arr[i] = nums1[i]; } for (int i = 0; i < b; i++) { arr[i+a] = nums2[b-i-1]; } }else{ for (int i = 0; i < b; i++) { arr[i] = nums2[i]; } for (int i = 0; i < a; i++) { arr[i+b] = nums1[a-1-i]; } } }else if(nums1[0] >= nums1[1] && nums2[0] <= nums2[1]){ if(nums1[a-1] <= nums2[0]){ for (int i = 0; i < a; i++) { arr[i] = nums1[a-1-i]; } for (int i = 0; i < b; i++) { arr[i+a] = nums2[i]; } }else{ for (int i = 0; i < b; i++) { arr[i] = nums2[i]; } for (int i = 0; i < a; i++) { arr[i+b] = nums1[a-1-i]; } } } }else{ for (int i = 0; i < a; i++) { arr[i] = nums1[i]; } for (int i = 0; i < b; i++) { arr[i+a] = nums2[i]; } } int right = arr.length-1; int left = 0; quickSort(arr,left,right); int tmp = arr.length; if(tmp % 2 == 0){ result = (arr[tmp/2] + arr[tmp/2 - 1]) / 2.0; }else{ result = arr[tmp/2]; } return result; } }
時間復雜度:O(log(min(m,n)))
運行結果:
【程序52】
給定一個字符串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為 1000。
/** * 【程序52】 * 給定一個字符串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為 1000。 */ public class Subject52 { public static void main(String[] args) { String str = "sdffttrrgfddfh"; String result= longestPalindrome(str); System.out.println(result); result = longestPalindrome1(str); System.out.println(result); } /** * Manacher算法 * @param str * @return */ private static String longestPalindrome1(String str) { char[] cStr = str.toCharArray(); //插入特殊符號 StringBuffer sBuffer = new StringBuffer(); sBuffer.append("#"); for (int i = 0; i < cStr.length; i++) { sBuffer.append(cStr[i]); sBuffer.append("#"); } int id =0; //回文的中心。 int max = 0; //回文最大長度。 //輔助數組 int[] p= new int[sBuffer.length()]; for (int i = 1; i < sBuffer.length(); i++) { if (i<max) { p[i] = Math.min(p[2*id-i], max-i); }else { p[i]= 1; } //判斷中心兩邊是否回文,是則++; while (i-p[i]>=0&&i+p[i]<sBuffer.length()&&sBuffer.charAt(i-p[i])==sBuffer.charAt(i+p[i])) { p[i]++; } if (i+p[i]>max) { max = i+p[i]; id = i; } } int maxl = 0 ; int maxid =0 ; for(int i =0 ;i<p.length;i++){ if(maxl<p[i]){ maxl=p[i]; maxid = i; } } //半徑包括id本身。id到第一個元素,id-r+1 int r = maxl-1; int start = maxid-r+1; int end = maxid+maxl-1; StringBuffer out = new StringBuffer(); for (int i = start; i < end; i++) { if (sBuffer.charAt(i)!='#') { out.append(sBuffer.charAt(i)); } } return out.toString(); } /** * 獲取最長回文數 * @param s * @return */ public static String longestPalindrome(String s) { String result = ""; char[] arr = s.toCharArray(); for(int i = 0 ; i < arr.length; i++){ for (int j = 0; j <= i; j++) { //判斷是否回文。 result = palindromeStr(s,arr,i,j); if(!"".equals( result) ){ return result; } } } return result; } /** * 判斷字符串是否是回文字符串 * @param s * @param arr * @param i * @param j * @return */ private static String palindromeStr(String s,char[] arr, int i, int j) { String result = ""; int start = j; int end = arr.length-(i-j)-1; while(start <= end){ if(arr[start] == arr[end]){ if(start+1 >= end){ result = s.substring(j,arr.length-(i-j)); return result; } start++; end--; }else{ break; } } return result; } }
時間復雜度:O(n)
運行結果:
【程序53】
將一個給定字符串根據給定的行數,以從上往下、從左到右進行 |\| 字形排列
import java.util.ArrayList; import java.util.List; /** * 【程序53】 * 將一個給定字符串根據給定的行數,以從上往下、從左到右進行 字形排列 * * 輸入: s = "LEETCODEISHIRING", numRows =4 * 輸出:"LDREOEIIECIHNTSG" * 解釋: * L D R * E O E I I * E C I H N * T S G */ public class Subject53 { public static void main(String[] args) { String s = "LEETCODEISHIRING"; int numRows = 4; String str = convert(s,numRows); System.out.println(str); } /** * * @param s * @param numRows * @return */ public static String convert(String s,int numRows){ if(numRows <= 1){ return s; } char[] arr = s.toCharArray(); //創建numRows個字符串 List<StringBuilder> list = new ArrayList<>(); for (int i = 0; i < numRows; i++) { StringBuilder stringBuffer = new StringBuilder(); list.add(stringBuffer); } int flag = 0; // 0表示順序,1表示逆序。 int size = 1; //在第幾行 for (int i = 0; i < arr.length; i++) { if(size == numRows){ flag = 1; } if(size == 1){ flag = 0; } list.get(size-1).append(arr[i]); if(flag == 0){ size++; } if(flag == 1){ size--; } } StringBuilder newStringBuffer = new StringBuilder(); for (int i = 0; i < numRows; i++) { newStringBuffer.append(list.get(i)); } return newStringBuffer.toString(); } }
時間復雜度:O(n)
運行結果:
【程序54】
給出一個 32 位的有符號整數,你需要將這個整數中每位上的數字進行反轉。
/** * 給出一個 32 位的有符號整數,你需要將這個整數中每位上的數字進行反轉。 */ public class Subject54 { public static void main(String[] args) { int x= 2147483641; int result = reverse(x); System.out.println(result); result = reverse2(x); System.out.println(result); } /** * 反轉 * @param x * @return */ public static int reverse(int x){ String str = x+""; char[] arr = str.toCharArray(); StringBuilder stringBuilder = new StringBuilder(); if(arr[0] == '-'){ stringBuilder.append('-'); for (int i = arr.length-1; i >= 1; i--) { stringBuilder.append(arr[i]); } }else{ for (int i = arr.length-1; i >= 0; i--) { stringBuilder.append(arr[i]); } } int result = 0; try { result = Integer.parseInt(stringBuilder.toString()); }catch (Exception e){ result = 0; } return result; } /** * 反轉2 * @param x * @return */ public static int reverse2(int x){ int rev = 0; while (x != 0) { int pop = x % 10; x /= 10; if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0; if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0; rev = rev * 10 + pop; } return rev; } }
時間復雜度:O(\log(x))
運行結果:
【程序55】
請你來實現一個 atoi 函數,使其能將字符串轉換成整數。
/** * 【程序55】 * 請你來實現一個 atoi 函數,使其能將字符串轉換成整數。 */ public class Subject55 { public static void main(String[] args) { String str = " -2147483649ww"; int i= myAtoi(str); System.out.println(i); } public static int myAtoi(String str) { int radix = 10; if (str == null) { return 0; }else{ str = str.trim(); } int result = 0; boolean negative = false; int i = 0, len = str.length(); int limit = -Integer.MAX_VALUE; int multmin; int digit; if (len > 0) { char firstChar = str.charAt(0); if (firstChar < '0') { // Possible leading "+" or "-" if (firstChar == '-') { negative = true; limit = Integer.MIN_VALUE; } else if (firstChar != '+') return 0; if (len == 1) // Cannot have lone "+" or "-" return 0; i++; } multmin = limit / radix; while (i < len) { // Accumulating negatively avoids surprises near MAX_VALUE digit = Character.digit(str.charAt(i++),radix); if (digit < 0) { break; } if (result < multmin) { result = limit; break; } result *= radix; if (result < limit + digit) { result = limit; break; } result -= digit; } } else { return 0; } return negative ? result : -result; } }
時間復雜度:O(n)
運行結果:
【程序56】
判斷一個整數是否是回文數。回文數是指正序(從左向右)和倒序(從右向左)讀都是一樣的整數。
考慮負數。
/** * 【程序56】 * 判斷一個整數是否是回文數。回文數是指正序(從左向右)和倒序(從右向左)讀都是一樣的整數。 */ public class Subject56 { public static void main(String[] args) { int x = 1; boolean flag = isPalindrome(x); System.out.println(flag); } /** * 判斷x是否是回文數 * @param x * @return */ public static boolean isPalindrome(int x) { if(x < 0){ return false; } if(x < 10){ return true; } int newi = 0; int num = x; while(true){ if(newi>0){ newi = newi*10; } int i = num%10 ; newi = newi+i; num = num/10; if(num <= 9){ newi = newi*10+num; break; } } if(newi == x){ return true; }else{ return false; } } }
時間復雜度:O(\log_{10}(n))
運行結果:
【程序57】
給你一個字符串 s 和一個字符規律 p,請你來實現一個支持 '.' 和 '*' 的正則表達式匹配。
'.' 匹配任意單個字符
'*' 匹配零個或多個前面的那一個元素
import java.util.HashMap; import java.util.Map; /** * 給你一個字符串 s 和一個字符規律 p,請你來實現一個支持 '.' 和 '*' 的正則表達式匹配。 * '.' 匹配任意單個字符 * '*' 匹配零個或多個前面的那一個元素 */ public class Subject57 { public static void main(String[] args) { Map<String ,String> map = new HashMap<>(); map.put("dddc","d*dddc"); //true; for (Map.Entry<String,String> entry :map.entrySet()){ System.out.println(entry.getKey()+" : "+entry.getValue()); System.out.println(isMatch(entry.getKey(),entry.getValue())); } } /** * 實現匹配規則 * @param s * @param p * @return */ public static boolean isMatch(String s, String p) { if (p.isEmpty()) return s.isEmpty(); boolean first_match = (!s.isEmpty() && (p.charAt(0) == s.charAt(0) || p.charAt(0) == '.')); if (p.length() >= 2 && p.charAt(1) == '*'){ return (isMatch(s, p.substring(2)) || (first_match && isMatch(s.substring(1), p))); } else { return first_match && isMatch(s.substring(1), p.substring(1)); } } }
時間復雜度:O(TP)
運行結果:
以上題目均來自:https://leetcode-cn.com/ ,如果你熱愛編碼,熱愛算法,該網站一定適合你。