本文收集了一些LeetCode 的一些中等难度的题目。
基础数据类型定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public  class  ListNode1  {    int  val;     ListNode1 next;     ListNode1(int  x) {         val = x;     }          public  ListNode1 (int  val , ListNode1 next) {         this .val = val;         this .next = next;     }     public  ListNode1 reverseLink (ListNode1 head)  {         ListNode1  head1  =  head, next1 = head.next, prev1 = null ;         while (head1 != null ){             head1.next = prev1;             prev1 = head1;             head1 = next1;             next1 = head1.next;           }         return  prev1;     } } 
 
Quick Start 给出两个非空链表来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。 如果我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。假设除了数字 0 之外,这两个数都不会以 0 开头。 示例:输入:(2 -> 4 -> 3) + (5 -> 6 -> 4);输出:7 -> 0 -> 8。原因:342 + 465 = 807
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public  static  ListNode1 problem (ListNode1 l1, ListNode1 l2)  {    ListNode1  head  =  new  ListNode1 (0 );     ListNode1  p1  =  l1, p2 = l2, re = head;     int  temp  =  0 ;      while  (p1 != null  || p2 != null  || temp != 0 ) {         if  (p1 != null  && p2 != null ) {             re.val = (p1.val + p2.val + temp) % 10 ;             temp = (p1.val + p2.val + temp) / 10 ;             p1 = p1.next;             p2 = p2.next;         } else  if  (p1 == null  && p2 != null ) {                  re.val = (p2.val + temp) % 10 ;             temp = (p2.val + temp) / 10 ;             p2 = p2.next;         } else  if  (p1 != null  && p2 == null ) {                re.val = (p1.val + temp) % 10 ;             temp = (p1.val + temp) / 10 ;             p1 = p1.next;         } else  if  (temp != 0 ) {             re.val = temp;             temp = 0 ;         }         if  (p1 != null  || p2 != null  || temp != 0 ) {             re.next = new  ListNode1 (0 );             re = re.next;         } else  {             re.next = null ;         }     }     return  head; } public  static  ListNode1 problem_pre (ListNode1 l1, ListNode1 l2)  {    ListNode1  head  =  new  ListNode1 (0 );     ListNode1  p1  =  l1, p2 = l2, re = head;     int  temp  =  0 ;      while  (p1 != null  || p2 != null  || temp != 0 ) {         int  sum  =  (p1 != null  ? p1.val : 0 )  + (p2 != null  ? p2.val : 0 ) + temp;         temp = sum / 10 ;         re.next = new  ListNode1 (sum % 10 );         p1 = p1 != null  ?  p1.next : null ;         p2 = p2 != null  ?  p2.next : null ;     }     return  head.next; } 
 
不含重复字符的最长子串长度 给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。  请注意,你的答案必须是子串的长度。 示例 1: 输入: “abcabcbb”。输出: 3。解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。 示例 2: 输入: “bbbbb”。输出: 1。解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。 示例 3: 输入: “pwwkew”。输出: 3。解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 public  static  int  problem (String strSrc)  {    if  (strSrc.equals("" ) || strSrc.length() == 0  || strSrc.length() == 1 ) {         System.out.println("源字符串<"  + strSrc + ">的最长子串<"  + strSrc + ">长度为 >> "  + strSrc.length());         return  strSrc.length();     }     String  subStr  =  ""  + strSrc.charAt(0 );     String  maxStr  =  subStr;     int  maxLen  =  maxStr.length();     int  count  =  0 ;     boolean  flag;     for  (int  i  =  1 ; i < strSrc.length(); ) {         int  j  =  0 ;         flag = true ;         for  (; j < subStr.length(); j++) {               if  (strSrc.charAt(i) == subStr.charAt(j)) {                  count++;                 i = i - subStr.length() + 1 ;                 subStr = ""  + strSrc.charAt(i);                 i += 1 ;                 flag = false ;                 break ;             }         }         if  (j == subStr.length() && flag && i < strSrc.length()) {              subStr = subStr + strSrc.charAt(i);             maxStr = maxStr.length() < subStr.length() ? subStr : maxStr;             maxLen = maxStr.length();             i += 1 ;         }     }     System.out.println("源字符串<"  + strSrc + ">的最长子串<"  + maxStr + ">长度为 >> "  + maxLen);     return  maxLen; } public  static  int  lengthOfLongestSubstring (String s)  {    if  (s.equals("" ) || s.length() == 0  || s.length() == 1 ) {         return  s.length();     }     String  subStr  =  ""  + s.charAt(0 );     int  maxLen  =  subStr.length();     boolean  flag;     for  (int  i  =  1 ; i < s.length(); i++) {         int  j  =  0 ;         flag = true ;         for  (; j < subStr.length(); j++) {               if  (s.charAt(i) == subStr.charAt(j)) {                  i = i - subStr.length() + 1 ;                 subStr = ""  + s.charAt(i);                 i += 1 ;                 flag = false ;                 break ;             }         }         if  (j == subStr.length() && flag && i < s.length()) {              subStr = subStr + s.charAt(i);             maxLen = maxLen > subStr.length() ? maxLen : subStr.length();             i += 1 ;         }     }     return  maxLen; } 
 
找出字符串中最长回文子串 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 示例 1:输入: “babad”。输出: “bab”。注意: “aba” 也是一个有效答案。 示例 2:输入: “cbbd”。输出: “bb”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public  static  String problem (String s)  {    String  result  =  "" ;     boolean  dp[][] = new  boolean [s.length()][s.length()];     for (int  i  =  0 ; i < s.length(); i++){         for (int  j  =  0 ; j < s.length(); j++){             dp[i][j] = false ;         }     }          for  (int  l  =  0 ; l < s.length(); l++) {         for  (int  i  =  0 ; i < s.length(); i++) {              int  j  =  i + l;              if  (j >= s.length()) {                 break ;             }             if  (l == 0 ) {                 dp[i][j] = true ;             } else  if  (l == 1 ) {                 dp[i][j] = (s.charAt(i) == s.charAt(j));             } else  {                 dp[i][j] = (dp[i + 1 ][j - 1 ] && s.charAt(i) == s.charAt(j));             }                          if (dp[i][j] && l + 1  > result.length()){                 result = s.substring(i, j + 1 );              }         }     }     return  result; } 
 
将给定字符串按给定行数Z字排列 将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。具体示例如下图所示。请你实现这个将字符串进行指定行数变换的函数: string convert(string s, int numRows);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public  static  String problem (String s, int  numRows)  {    if (numRows < 2 ){         return  s;     }     List<StringBuilder> rows = new  ArrayList <StringBuilder>();       for (int  i  =  0 ; i < numRows; i++) {         rows.add(new  StringBuilder ());     }     int  i  =  0 , flag = -1 ;     for (char  c : s.toCharArray()) {          rows.get(i).append(c);          if (i == 0  || i == numRows - 1 ){              flag = -flag;         }         i += flag;     }     StringBuilder  res  =  new  StringBuilder ();     for (StringBuilder row : rows) {         res.append(row);     }     return  res.toString(); } 
 
字符串转整数的实现函数 atoi 请你来实现一个 atoi 函数,使其能将字符串转换成整数。首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。接下来的转化规则如下 : 如果第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字字符组合起来,形成一个有符号整数。假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成一个整数。该字符串在有效的整数部分之后也可能会存在多余的字符,那么这些字符可以被忽略,它们对函数不应该造成影响。 注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换,即无法进行有效转换。在任何情况下,若函数不能进行有效的转换时,请返回 0 。 提示:本题中的空白字符只包括空格字符 ‘ ‘ 。假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231,  231 − 1]。如果数值超过这个范围,请返回  INT_MAX (231 − 1) 或 INT_MIN (−231) 。 示例 1: 输入: “42”。输出: 42。 示例 2: 输入: “   -42”。输出: -42     解释: 第一个非空白字符为 ‘-‘是一个负号。尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。 示例 3: 输入: “4193 with words”  输出: 4193。解释: 转换截止于数字 ‘3’ ,因为它的下一个字符不为数字。 示例 4: 输入: “words and 987”。输出: 0。解释: 第一个非空字符是 ‘w’, 但它不是数字或正、负号。因此无法执行有效的转换。 示例 5: 输入: “-91283472332”。输出: -2147483648。解释: 数字”-91283472332”超过32位有符号整数范围。返回 INT_MIN (−231) 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 public  static  int  problem (String str)  {    if  (str.length() == 0  || str.equals("" )) {         return  0 ;     }     int  i  =  0 , flag = 0 ;      double  target  =  0 ;     String  numStr  =  "" ;     for  (; i < str.length(); i++) {         if  (str.charAt(i) == ' '  && numStr.length() == 0 ) {              continue ;         }         if  (flag == 0  && (str.charAt(i) < '0'  || str.charAt(i) > '9' )              && (str.charAt(i) != '-'  && str.charAt(i) != '+' )) {                  return  0 ;         }         if  (flag == 0  && numStr.length() == 1  && (str.charAt(i) > '9'  || str.charAt(i) < '0' )) {                           return  0 ;         }         if  (flag == 1  && (str.charAt(i) > '9'  || str.charAt(i) < '0' )) {              break ;         }         if  (flag == 0  && (str.charAt(i) == '-'  || str.charAt(i) == '+' )) {              numStr = numStr + str.charAt(i);         }         if  (str.charAt(i) >= '0'  && str.charAt(i) <= '9' ) {             flag = 1 ;             numStr = numStr + str.charAt(i);             target = target 10  + (str.charAt(i) - '0' );         }     }     if  (!numStr.equals("" ) && numStr.charAt(0 ) == '-' ) {         target = 0  - target;     }     if  (target > Math.pow(2 , 31 ) - 1  || target < Math.pow(-2 , 31 )) {         return  numStr.charAt(0 ) == '-'  ? (int ) Math.pow(-2 , 31 ) : (int ) Math.pow(2 , 31 );     }     return  (int ) target; } 
 
最大容量的容器 给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。说明:你不能倾斜容器,且 n 的值至少为 2。 示例:输入:[1,8,6,2,5,4,8,3,7]。输出:49
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public  static  int  problem (int [] height)  {    if  (height == null  || height.length <= 1 ) {         return  0 ;     }     int  bottomLen, target = 0 ;     for  (int  i  =  0 ; i < height.length - 1 ; i++) {         for  (int  j  =  i + 1 ; j < height.length; j++) {             bottomLen = j - i;             int  temp  =  bottomLen * Math.min(height[i], height[j]);             target = Math.max(target, temp);         }     }     return  target; } 
 
罗马数字转整数 罗马数字包含以下七种字符:I,V,X,L,C,D和M。 字符(数值)对应关系:I(1)、V(5)、X(10)、L(50)、C(100)、D(500)、M(1000) 例如, 罗马数字 2 写做II,即为两个并列的 1。12 写做XII,即为X+II。 27 写做XXVII, 即为XX+V+II。 通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做IIII,而是IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为IX。这个特殊的规则只适用于以下六种情况: I可以放在V(5)        和X(10)       的左边,来表示 4        和9。 X可以放在L(50)     和C(100)     的左边,来表示 40     和90。 C可以放在D(500)  和M(1000)  的左边,来表示 400  和900。 给定一个罗马数字,将其转换成整数。输入确保在 1到 3999 的范围内 示例 1: 输入:”III”            输出: 3 示例 2: 输入:”IV”            输出: 4 示例 3: 输入:”IX”                输出: 9 示例 4: 输入:”LVIII”            输出: 58         解释: L = 50, V= 5, III = 3。 示例 5: 输入:”MCMXCIV”      输出: 1994         解释: M = 1000, CM = 900, XC = 90, IV = 4。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public  static  String problem (int  num)  {    if  (num <= 0 ) {         return  "" ;     }     String sub[] = {"I" , "II" , "III" , "IV" , "V" , "IX" , "X" , "XL" , "L" , "XC" , "C" , "CD" , "D" , "CM" , "M" };     int  cons[] = {1 , 2 , 3 , 4 , 5 , 9 , 10 , 40 , 50 , 90 , 100 , 400 , 500 , 900 , 1000 };     String  target  =  "" ;     for  (int  i  =  cons.length - 1 ; i >= 0 ; ) {         if  (num == 0 ) {             break ;         }         if  (num / cons[i] == 0 ) {              i--;         }         if  (num / cons[i] != 0 ) {              target = target + sub[i];             num -= cons[i];         }     }     return  target; } 
 
数组中三数之和为0的三元组 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。注意:答案中不可以包含重复的三元组。 示例:给定数组 nums = [-1, 0, 1, 2, -1, -4],满足要求的三元组集合为:[ [-1, 0, 1], [-1, -1, 2] ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public static List<List<Integer>> problem8(int[] nums) {     List<List<Integer>> re = new ArrayList<>();     // 找出所有的三元组 [a, b, c] 对应的指针分别为 i j k     int n = nums.length;     Arrays.sort (nums);  // 从小到大排序     for  (int i = 0; i < nums.length; ++i) {         if  (i > 0 && nums[i] == nums[i - 1]) {//  跳过数组中的重复元素             continue ;         }         int k = n - 1; // c对应的指针初始指向数组的最右端         for  (int j = i + 1; j < nums.length; ++j) {             if  (j > i + 1 && nums[j] == nums[j - 1]) {//  跳过数组中的重复元素                 continue ;             }             while  (k > j && nums[i] + nums[j] + nums[k] > 0) {  // 保证 b 的指针在 c 的指针的左侧                 --k;             }             // 如果指针重合,随着 b增大 不再存在满足 a+b+c=0 并且 b < c 的 c             if  (j == k) {                 break ;             }             if  (nums[i] + nums[j] + nums[k] == 0) {                 List<Integer> list = new ArrayList<Integer>();                 list.add(nums[i]);                 list.add(nums[j]);                 list.add(nums[k]);                 re.add(list);             }         }     }     return  re; } 
 
数组中与给定值最接近的三数之和 给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。 示例:输入:nums = [-1,2,1,-4], target = 1    输出:2。解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。 提示:3 <= nums.length <= 10^3;-10^3 <= nums[i] <= 10^3;-10^4 <= target <= 10^4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public  static  int  problem (int [] nums, int  target)  {         Arrays.sort(nums);       int  res  =  nums[0 ] + nums[1 ] + nums[2 ];     if  (nums.length == 3 ) {          return  res;     }     if  (res - target == 0 ) {          return  target;     }     for  (int  i  =  0 ; i < nums.length; ++i) {         if  (i > 0  && nums[i] == nums[i - 1 ]) {              continue ;         }         int  k  =  nums.length - 1 ;          int  j  =  i + 1 ;         while  (k > j) {              int  temp  =  nums[i] + nums[j] + nums[k];             if  (temp == target) {                 return  target;             }             if  (Math.abs(res - target) >= Math.abs(temp - target)) {                 res = temp;             }                          if  (temp > target) {                  k = k - 1 ;                 while  (j < k && nums[k] == nums[k + 1 ]) {                      k = k - 1 ;                 }             } else  if  (temp < target) {                  j = j + 1 ;                 while  (j < k && nums[j] == nums[j - 1 ]) {                      j = j + 1 ;                 }             }         }     }     return  res; } 
 
字母异位词分组 49. 字母异位词分组 
问题描述 :给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
示例 1: 
输入:  strs = [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]
输出:  [[“bat”],[“nat”,”tan”],[“ate”,”eat”,”tea”]]
解释: 
在 strs 中没有字符串可以通过重新排列来形成 "bat"。 
字符串 "nat" 和 "tan" 是字母异位词,因为它们可以重新排列以形成彼此。 
字符串 "ate" ,"eat" 和 "tea" 是字母异位词,因为它们可以重新排列以形成彼此。 
 
示例 2: 
输入:  strs = [“”]
输出:  [[“”]]
示例 3: 
输入:  strs = [“a”]
输出:  [[“a”]]
提示: 
1 <= strs.length <= 104 
0 <= strs[i].length <= 100 
strs[i] 仅包含小写字母 
 
 
1 2 3 4 5 6 7 8 9 10 11 public  List<List<String>> groupAnagrams (String[] strs)  {    HashMap<String, List<String>> map = new  HashMap <>();     for  (int  i  =  0 ; i < strs.length; i++) {         char [] temp = strs[i].toCharArray();         Arrays.sort(temp);          List<String> list = map.getOrDefault(new  String (temp), new  ArrayList <>());         list.add(strs[i]);         map.put(new  String (temp), list);     }     return  new  ArrayList <>(map.values()); } 
 
反转每对括号间的子串 给出一个字符串 s(仅含有小写英文字母和括号)。请你按照从括号内到外的顺序,逐层反转每对匹配括号中的字符串,并返回最终的结果。注意,结果中不应包含任何括号。 示例 1:输入:s = “(abcd)”。输出:”dcba” 示例 2:输入:s = “(u(love)i)”。输出:”iloveu”。解释:先反转子字符串 “love” ,然后反转整个字符串。 示例 3:输入:s = “(ed(et(oc))el)”。输出:”leetcode”。解释:先反转子字符串 “oc” ,接着反转 “etco” ,然后反转整个字符串。 提示:1 <= s.length <= 2000;s 中只有小写英文字母和括号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public  static  String reverseParentheses (String s)  {    StringBuilder  sb  =  new  StringBuilder ();     char [] arr = s.toCharArray();     Stack<Integer> stack = new  Stack <>();     for  (int  i  =  0 ; i < arr.length; i++) {         if  (arr[i] == '(' ) {             stack.push(i);         }         if  (arr[i] == ')' ) {             reverse(arr, stack.pop() + 1 , i - 1 );         }     }     for  (int  i  =  0 ; i < arr.length; i++) {         if  (arr[i] != ')'  && arr[i] != '(' ) {             sb.append(arr[i]);         }     }     return  sb.toString(); } public  static  void  reverse (char [] arr, int  left, int  right)  {    while  (right > left) {         char  tmp  =  arr[left];         arr[left] = arr[right];         arr[right] = tmp;         right--;         left++;     } }