Leetcode算法代码解答总结——长文慎入!(持续更新)

        ——写在前面,复习算法一段时间了,在此记录一下自己写过的算法代码,算是做个总结,供自己以后回顾。

43.字符串相乘

给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。

示例 1:

输入: num1 = "2", num2 = "3"
输出: "6"

示例 2:

输入: num1 = "123", num2 = "456"
输出: "56088"

思路:大数相乘,用一个int数组存每一位的相乘数,像小学时学的乘法运算那样算

class Solution {
    public String multiply(String num1, String num2) {
        if(num1.equals("0")||num2.equals("0"))
            return "0";
        int len1 = num1.length();
        int len2=num2.length();
        int res_len=len1+len2;
        int res[]=new int [res_len];
        for(int i=len1-1;i>=0;i--){
            int n1=num1.charAt(i)-48;
            int tmp=0;
            for(int j=len2-1;j>=0;j--){
                int n2=num2.charAt(j)-48;
                res[i+j+1]=n1*n2+res[i+j+1]+tmp;
                tmp =res[i+j+1]/10;
                res[i+j+1]=res[i+j+1]%10;
            }
            res[i]+=tmp;
        }
        StringBuilder sb=new StringBuilder();
        int flag=1;
        for(int i=0;i<res_len;i++){
            if(res[i]==0&&flag==1)
                continue;
            sb.append(res[i]);
            flag=0;
        }
        return sb.toString();
    }
}

322. 零钱兑换

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1

class Solution {
    public int coinChange(int[] coins, int amount) {
        int size=coins.length;
        int dp[]=new int[amount+1];
        //0x3F3F3F表示一个很大的数,dp[j]表示找零金额为j时的最少硬币数
        Arrays.fill(dp,0x3F3F3F);
        dp[0]=0;
        //遍历i种硬币,新的最少硬币数会覆盖旧的最少硬币数
        for(int i=0 ;i<size;i++){
            for(int j=coins[i];j<=amount;j++){ 
                //如果拿一个coins[i]硬币,硬币数就是dp[j-coins[i]]+1,但如果金额为j-coins[i]不                           
                //能找零,则找零最少硬币数为0x3F3F3F+1,则最少硬币还是dp[j](0x3F3F3F),归根到底
                //还是不能找零
                dp[j]=Math.min(dp[j-coins[i]]+1,dp[j]);
            }
        }
        if(dp[amount]==0x3F3F3F)
            dp[amount]=-1;
        return dp[amount];
    }
}

62不同路径

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

问总共有多少条不同的路径?

输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向右 -> 向下
2. 向右 -> 向下 -> 向右
3. 向下 -> 向右 -> 向右

考察:dp动态规划,dp[i][j]=dp[i-1][j]+dp[i][j-1]

class Solution {
    public int uniquePaths(int m, int n) {
        if(m==1&&n==1)
            return 1;
        int dp[][]=new int[m][n];
        for(int i=1;i<n;i++){  //行数为1,只能横着走,走法只有一种
            dp[0][i]=1;
        }
        for(int j=1;j<m;j++){  //列数为1,只能竖着走,走法只有一种
           dp[j][0]=1;
        }
        for(int i=1;i<m;i++){
           for(int j=1;j<n;j++){
               dp[i][j]=dp[i-1][j]+dp[i][j-1];  //要么从上面下来,要么从左边过来,走法为这两种情况之和
           }
        }
        return dp[m-1][n-1];
    }
}

 

69x 的平方根

实现 int sqrt(int x) 函数。

计算并返回 x 的平方根,其中 是非负整数。

由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

示例 2:

输入: 8
输出: 2
说明: 8 的平方根是 2.82842..., 
     由于返回类型是整数,小数部分将被舍去。

考察:二分搜索

class Solution {
    public int mySqrt(int x) {
       int i=1,j=x;
       while(i<=j)
       {
           int mid=(i+j)/2;
           if(mid<x/mid)
               i=mid+1;
           else if(mid>x/mid)
               j=mid-1;
           else return mid;
       }
        return j;
    }
}
//另一种做法  return  (int)Math.sqrt(x);

94二叉树的中序遍历

给定一个二叉树,返回它的中序 遍历。

示例:

输入: [1,null,2,3]
   1
    \
     2
    /
   3

输出: [1,3,2]

考察:有两种做法,递归很简单,迭代复杂点

class Solution {
    List<Integer> res=new ArrayList<Integer>();
    public void  search(TreeNode root){  //这是递归做法
        if(root==null)
            return;
        if(root.left!=null)
           search(root.left);
        res.add(root.val);
        if(root.right!=null)
           search(root.right);
    }
    public List<Integer> inorderTraversal(TreeNode root) {
       search(root);
       return res;
    }
}

67二进制求和

给定两个二进制字符串,返回他们的和(用二进制表示)。

输入为非空字符串且只包含数字 1 和 0

示例 1:

输入: a = "11", b = "1"
输出: "100"

考察:math,相加的进位

class Solution {
    public String addBinary(String a, String b) {
        int aLen=a.length()-1;
        int bLen=b.length()-1;
        int m=0;
        int n=0;
        StringBuilder res=new StringBuilder();//用数组来存结果也可以,然后把数组转化为String,最后如果有进位则在结果前加个"1"
        while(aLen>=0&&bLen>=0){
            int tmp=a.charAt(aLen)-'0'+b.charAt(bLen)-'0'+n;
            m=tmp%2;
            n=tmp/2;
            res.insert(0,String.valueOf(m));
            aLen--;
            bLen--;            
        }
        while(aLen>=0){
            int tmp=a.charAt(aLen)-'0'+n;
            m=tmp%2;
            n=tmp/2;
            res.insert(0,String.valueOf(m));
            aLen--;
        }
        while(bLen>=0){
            int tmp=b.charAt(bLen)-'0'+n;
            m=tmp%2;
            n=tmp/2;
            res.insert(0,String.valueOf(m));
            bLen--;
        }
        if(n>0){
            res.insert(0,"1");
        }
        return res.toString();
    }
}

 

49字母异位词分组

给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

示例:

输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
  ["ate","eat","tea"],
  ["nat","tan"],
  ["bat"]
]

考察:HashMap

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String,List<String>>map=new HashMap<>();
        List<List<String>>result=new ArrayList<>();
        if(strs.length==0)
            return result;
        for(String s:strs){
            char[] tmp=s.toCharArray();
            Arrays.sort(tmp);
            String keyStr=new String(tmp);
            if(!map.containsKey(keyStr))
            {
                List<String> item=new ArrayList<String>();
                item.add(s);
                map.put(keyStr,item);
                result.add(item);
            }
            else
               map.get(keyStr).add(s);
        }
        return result;
    }
}

 

206反转链表

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

考察:递推遍历链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if(head==null)
            return null;
        ListNode cur=head.next;
        ListNode next;
        head.next=null;
        while(cur!=null){
            next=cur.next;
            cur.next=head;
            head=cur;
            cur=next;
        }
        return head;
    }
}

 

23合并K个排序链表

合并 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。

示例:

输入:
[
  1->4->5,
  1->3->4,
  2->6
]
输出: 1->1->2->3->4->4->5->6

考察:两指针,归并

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoList(ListNode first,ListNode two){
        if(first==null)
            return two;
        if(two==null)
            return first;
        ListNode node=new ListNode(0);
        if(first.val<two.val){
            node.val=first.val;
            node.next=mergeTwoList(first.next,two);
        }
        else{
            node.val=two.val;
            node.next=mergeTwoList(first,two.next);
        }
        return node;
    }
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists==null||lists.length==0)
            return null;
        else if(lists.length==1)
            return lists[0];
        else{
            int begin=0,end=lists.length-1;
            while(end>0){
                begin=0;
                while(begin<end){
                    lists[begin]=mergeTwoList(lists[begin],lists[end]);
                    begin++;
                    end--;
                }
            }
            return lists[0];
        }
    }
}

24两两交换链表中的节点

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

示例:

给定 1->2->3->4, 你应该返回 2->1->4->3.

考察:链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode swapPairs(ListNode head) {
        if(head==null||head.next==null)
            return head;
        ListNode second=head.next;
        ListNode third=second.next;
        second.next=head;
        head.next=swapPairs(third);
        return second;
    }
}

 

98、验证是否是二叉搜索树:给定一个二叉树,判断其是否是一个有效的二叉搜索树。

考察:二叉搜索树的中序遍历是递增(或递减)的,通过递归进行中序遍历

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    boolean isFirst=true;
    int lastval;
    public boolean isValidBST(TreeNode root) {
       if(root ==null){
           return true;
       }
       if(!isValidBST(root.left)){
           return false;
       }
       if(!isFirst&&lastval>=root.val)
           return false;
       isFirst=false;
       lastval=root.val;
       if(!isValidBST(root.right)){
           return false;
       }
       return true;
    }
}

22括号生成

给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。

例如,给出 = 3,生成结果为:

[
  "((()))",
  "(()())",
  "(())()",
  "()(())",
  "()()()"
]

考察:深度优先搜索(dfs),栈,括号匹配

class Solution {
    int left,right; //分别记录'('和')'的剩余数量
    LinkedList <Character> stack=new LinkedList<>(); //栈,存储左括号'('
    char item[]; //记录每种情况的括号排列
    int len;
    List<String> result=new LinkedList<>();
    public void dfs(int depth){
        if(depth==len-1){  //遍历到最后一个括号,一定是')'
            item[len-1]=')';
            String tmp=new String(item);
            result.add(tmp);
        }
        else {
            if(left!=0){
                stack.addFirst('(');
                item[depth]='(';
                left--;
                dfs(depth+1);
                left++;//回溯
                stack.poll();
            }
            if(right!=0&&!stack.isEmpty()){  //当')'剩余数不为0且栈中有'('时,可以取出一个左括号匹配
                stack.poll();
                item[depth]=')';
                right--;
                dfs(depth+1);
                right++; //回溯
                stack.addFirst('(');
            }
        }
    }
    public List<String> generateParenthesis(int n) {
        left=n-1;
        right=n;
        len=2*n;
        item=new char[n*2];
        item[0]='(';
        stack.addFirst('(');
        dfs(1);
        return result;
    }
}

 

127. 单词接龙

给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:

  1. 每次转换只能改变一个字母。
  2. 转换过程中的中间单词必须是字典中的单词。

说明:

  • 如果不存在这样的转换序列,返回 0。
  • 所有单词具有相同的长度。
  • 所有单词只由小写字母组成。
  • 字典中不存在重复的单词。
  • 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。

考察:广度优先搜索,最短路径,注意:set的查找速度比list快很多

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        if(!wordList.contains(endWord))
            return 0;
        int level=1,curnum=1,nextnum=0;
        LinkedList<String>q=new LinkedList<String>();
        Set<String>visited=new HashSet<String>();
        q.add(beginWord);
        visited.add(beginWord);
        Set dic=new HashSet(wordList);
        while(!q.isEmpty()){
           String str=q.poll();
           curnum--;           
           int len=str.length();
            for(int i=0;i<len;i++){
                char[]word=str.toCharArray();
                for(char j='a';j<='z';j++){
                   word[i]=j;
                   String tmp=new String(word);
                    if(tmp.equals(endWord)){
                       return level+1;
                    }
                    if(dic.contains(tmp)&&!visited.contains(tmp)){
                       q.add(tmp);
                       nextnum++;
                       visited.add(tmp);
                    }
                }
            }
            if(curnum==0){
               level++;
               curnum=nextnum;
               nextnum=0;
            }
        }
        return 0;
    }
}

12、实现strStr():

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回  -1

考察:KMP算法

class Solution {

    public int strStr(String haystack, String needle) {

        char []nee=needle.toCharArray();
        char []hay=haystack.toCharArray();
        int l1=hay.length;
        int l2=nee.length;
        if(l2==0)
            return 0;
        int next[]=new int[l2];
        next[0]=-1;//计算next[]数组,当没有公共前后缀时,next[i]=-1;
        for(int i=1;i<l2;i++){
           int t=next[i-1];
           while(nee[t+1]!=nee[i]&&t>=0) 
               t=next[t];
           if(nee[t+1]==nee[i])
               next[i]=t+1;
           else
               next[i]=-1;
        }
        int i=0,j=0;//遍历查找,时间复杂度为m+n
        while(i<l1){
           if(hay[i]==nee[j]){
               i++;j++;
               if(j==l2)
                   return i-l2;
           }
           else{
               if(j==0)
                   i++;
               else{
                   j=next[j-1]+1;
               }
           }
        }
        return -1;
    }
}

 

12整数转罗马数字

罗马数字包含以下七种字符: I, V, X, LCD 和 M

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。

考察:二维数组,math,指针遍历字符串。

class Solution {
    public String intToRoman(int num) {
        String str=String.valueOf(num);
        String [][] arr={{"I","II","III","IV","V","VI","VII","VIII","IX"},
                       {"X","XX","XXX","XL","L","LX","LXX","LXXX","XC"},
                       {"C","CC","CCC","CD","D","DC","DCC","DCCC","CM"},
                       {"M","MM","MMM"}
                      };
        int len=str.length();
        StringBuilder sb=new StringBuilder();
        for(int i=0;i<len;i++){
            int tmp=str.charAt(i)-'0';
            String out;
            if(tmp==0)
                continue;
            if(len-i==4){
                out=arr[3][tmp-1];
                sb.append(out);
            }
            else if(len-i==3){
                out=arr[2][tmp-1];
                sb.append(out);
            }
            else if(len-i==2){
                out=arr[1][tmp-1];
                sb.append(out);
            }
            else{
                sb.append(arr[0][tmp-1]);
            }
        }
        return sb.toString();
    }
}

13罗马数字转整数

罗马数字包含以下七种字符:I, V, X, LCD 和 M

给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。

考察:swich分支,math

class Solution {
    public int romanToInt(String s) {
        int index[]={1,5,10,50,100,500,1000};
        char[] arr=s.toCharArray();
        int len=arr.length;
        int last=index[getIndex(arr[0])];
        int result=0;
        if(len==1)
            return last;
        int tmp=0;
        for(int i=1;i<len;i++){
            tmp=index[getIndex(arr[i])];
            if(last<tmp)
                result-=last;
            else result+=last;
            last=tmp;
        }
        result+=tmp;
        return result;
    }
    public int getIndex(char x){
        switch(x){
                case 'I' :return 0;
                case 'V' :return 1;
                case 'X' :return 2;
                case 'L' :return 3;
                case 'C' :return 4;
                case 'D' :return 5;
                case 'M' :return 6;
            default: return -1;
        }
    }
}

 

125. 验证回文串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

考察:两指针

class Solution {
    public boolean isPalindrome(String s) {
        if(s==null||s.length()==0)
            return true;
        s=s.toLowerCase();
        int len=s.length();
        char[] arr=new char[len];
        int j=0;
        for(int i=0;i<len;i++){
            char tmp=s.charAt(i);
            if(tmp>='a'&&tmp<='z'||tmp>='0'&&tmp<='9')
                arr[j++]=tmp;
        }
        int low=0,high=j-1;
        while(low<high){
            if(arr[low]==arr[high])
            {
                low++;
                high--;
            }
            else
                return false;
        }
        return true;
    }
}

 

88. 合并两个有序数组

 

给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。

考察:两指针,归并,归并排序的归并部分思路

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int []asis=new int[m];//辅助数组,把nums1中的m个数拷贝出来
        for(int i=0;i<m;i++){
           asis[i]=nums1[i];
        }
        int a=0,b=0;//a,b为两个指向nums1和nums2开头的指针
        int i=0;
        while(i<m+n){
            if(a==m)//nums1中没数据了
                nums1[i++]=nums2[b++];
            else if(b==n) //nums2中没数据了
                nums1[i++]=asis[a++];
            else if(asis[a]<nums2[b]){
                nums1[i++]=asis[a++];  //nums1的数比nums2的数小
            }
            else {
                nums1[i++]=nums2[b++];  //nums2的数小
            }
        }
    }
}

 

73、矩阵置零

 

给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法

考察:数组,先标记再最后置零

class Solution {
    public void setZeroes(int[][] matrix) {
        int rlen=matrix.length;
        int clen=matrix[0].length;
        boolean row[]=new boolean[rlen];
        boolean col[]=new boolean[clen];
        for(int i=0;i<rlen;i++){
           for(int j=0;j<clen;j++){
               if(matrix[i][j]==0){
                   row[i]=true;
                   col[j]=true;
               }
           }
        }
        for(int i=0;i<rlen;i++){
            for(int j=0;j<clen;j++){
                if(row[i]||col[j])
                    matrix[i][j]=0;
            }
        }
    }
}

27移除元素

给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。

考察:快排中swap的部分

class Solution {
    public int removeElement(int[] nums, int val) {
        int len=nums.length;
        int right=len-1;
        int i=0;
        while(i<=right){
            if(nums[i]==val){
                nums[i]=nums[right--];
            }
            else i++;
        }
        return right+1;
    }
}

 

16、有效的数字:

验证给定的字符串是否为数字。

例如:
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false

"2e10" => true

考察:math,一个数字是否合法,指针遍历字符串,细节

class Solution {
    public boolean isNumber(String s) {
        s=s.trim();
        int len=s.length();
        if(len==0||s==null)
            return false;
        int i=0;
        boolean hasDot=false;
        boolean hasE=false;
        boolean hasDigit=false;
        if(s.charAt(i)=='e'||s.charAt(len-1)=='e'||s.charAt(len-1)=='+'||s.charAt(len-1)=='-')
            return false;
        if(s.charAt(i)=='-'||s.charAt(i)=='+'){
            i++;
        }
        while(i<len){
           if(s.charAt(i)>='0'&&s.charAt(i)<='9'){
               i++;
               hasDigit=true;
           }
           else if(s.charAt(i)=='e'&&hasE==false&&hasDigit==true){
               i++;
               hasE=true;
               if(s.charAt(i)=='+'||s.charAt(i)=='-'){
                   i++;
               }
           }
           else if(s.charAt(i)=='.'&&hasDot==false&&hasE==false){
               i++;
               hasDot=true;
           }
           else return false;
        }
        if(hasDigit==false)
            return false;
        return true;
    }
}

1、给定一个没有重复数字的序列,返回其所有可能的全排列。

考察:深度优先搜索(dfs)

class Solution {
    int []visit;
    List<List<Integer>> result;
    int len;
    int [] Allnums;
    int [] result_arr;
    void dfs(int depth){
    	if(depth==len){
    		List <Integer> item=new ArrayList<>();
    		int arrLen=result_arr.length;
    		for(int j=0;j<arrLen;j++){
    			item.add(result_arr[j]);
    		}
    		result.add(item);
    	}
    	else{
    		for(int i=0;i<len;i++){
    			if(visit[i]==0){
    				result_arr[depth]=Allnums[i];
    				visit[i]=1;
    				dfs(depth+1);
    				visit[i]=0;
    			}
    		}
    	}
    }
    public List<List<Integer>> permute(int[] nums) {
        Allnums=nums;
    	result=new ArrayList<>();
        len=nums.length;
        result_arr=new int[len];
        visit=new int[len];
        dfs(0);
        return result;
    }
}

2、给定一个可包含重复数字的序列,返回所有不重复的全排列。

考察:深度优先搜索(dfs)

class Solution {
     int [] input;
	 int len;
	 int [] result;
	 List <List<Integer>> output;
	 Map<Integer, Integer> map;
	 Set<Integer> set;
	 int keylen;
	 void dfs(int depth){
		if(depth==len){
			List<Integer> AddToOutput=new ArrayList<Integer>();
			for(int k=0;k<len;k++){
				AddToOutput.add(result[k]);
			}
		    output.add(AddToOutput);
		    return;
		}
        for(int i=0;i<keylen;i++){
        	int value=map.get(input[i]);
        	if(value>=1){
        		result[depth]=input[i];
        		map.put(input[i], value-1);
        		dfs(depth+1);
        		map.put(input[i], value);

        	}
        }
	}


    public List<List<Integer>> permuteUnique(int[] nums) {
    	len=nums.length;
    	map=new HashMap<Integer, Integer>();
    	for(int i=0;i<len;i++){
    		if(map.get(nums[i])==null){
    			map.put(nums[i], 1);
    		}
    		else{
    			int tmp=map.get(nums[i]);
    			map.put(nums[i],tmp+1);
    		}
    	}
    	set=map.keySet();
    	keylen=set.size();
    	input=new int[keylen];
    	Iterator<Integer>it=set.iterator();
    	int cnt=0;
    	while(it.hasNext()){
    		input[cnt++]=it.next();
    	}
    	result=new int[len];
    	output=new ArrayList<>();
        dfs(0);
        return output;
    }
}

3、求最大子序和:给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

考察:动态规划

class Solution {
    public int maxSubArray(int[] nums) {
       int len=nums.length;
       int []sum=new int[len];
       int []maxsubsum=new int[len];
       sum[0]=nums[0];
       maxsubsum[0]=nums[0];
        for(int i=1;i<len;i++){
           if(sum[i-1]<0)
               sum[i]=nums[i];
            else{
               sum[i]=sum[i-1]+nums[i];
            }
        }
        for(int i=1;i<len;i++){
            maxsubsum[i]=Math.max(maxsubsum[i-1],sum[i]);
        }
        return maxsubsum[len-1];
    }
}

 

5、二叉树的层次遍历

考察:广度优先搜索(bfs)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        LinkedList <TreeNode> q=new LinkedList<TreeNode>();
        List <List<Integer>> result=new LinkedList<>();
        if(root==null)
            return result;
        List <Integer> first=new LinkedList<Integer>();
        first.add(root.val);
        result.add(first);               
        q.offer(root);      
        int curnum=1;
        int nextnum=0;
        List <Integer> item=new LinkedList<Integer>();
        while(!q.isEmpty()){
            TreeNode t=q.poll();
            curnum--;
            if(t.left!=null){
                item.add(t.left.val);
                q.offer(t.left);
                nextnum++;
            }
            if(t.right!=null){
                item.add(t.right.val);
                q.offer(t.right);
                nextnum++;
            }
            if(curnum==0){
               curnum=nextnum;
               nextnum=0;
               if(!item.isEmpty())
               {
                   result.add(item);
                   item=new LinkedList<Integer>();
               }                
            }

        }
        return result;
    }
}

6、合并区间:给出一个区间的集合,请合并所有重叠的区间

考察:排序(快速排序),归并思路

/**
 * Definition for an interval.
 * public class Interval {
 *     int start;
 *     int end;
 *     Interval() { start = 0; end = 0; }
 *     Interval(int s, int e) { start = s; end = e; }
 * }
 */

class Solution {
    public void quickSort(Interval[] input,int low,int high){
         if(low>=high)
             return ;
         int v=input[low].start;
         int left=low,right=high;
         int i=low+1;
         while(i<=right){
            int tmp=input[i].start;
            if(tmp>v){
                Interval tmp2=input[i];
                input[i]=input[right];
                input[right--]=tmp2;
            }
            else if(tmp<v){
                Interval tmp2=input[i];
                input[i]=input[left];
                input[left++]=tmp2;
            }
            else i++;
         }
         quickSort(input,low,left-1);
         quickSort(input,right+1,high);
    }
    public List<Interval> merge(List<Interval> intervals) {
         List<Interval> res=new ArrayList<Interval>();     
         int len=intervals.size();
         if(len==0)
             return res;
         Interval [] input= new Interval[len];
         intervals.toArray(input);
         quickSort(input,0,len-1);
         Interval item=input[0];
         for(int i=1;i<input.length;i++){
        	Interval tmp=input[i];
        	if(tmp.start>item.end)
        		{
        		  res.add(item);
        		  item=tmp;
        		}
        	else{
        		item.end=Math.max(item.end, tmp.end);
        	}
        }
        res.add(item);
        return res;
    }
}

7、插入区间:

给出一个无重叠的 ,按照区间起始端点排序的区间列表。

在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。

考察:归并思路

/**
 * Definition for an interval.
 * public class Interval {
 *     int start;
 *     int end;
 *     Interval() { start = 0; end = 0; }
 *     Interval(int s, int e) { start = s; end = e; }
 * }
 */
class Solution {
    public List<Interval> insert(List<Interval> intervals, Interval newInterval) {
        List<Interval> res=new ArrayList<Interval>();
        int len=intervals.size();
        if(len==0){
            res.add(newInterval);
            return res;
        }
        int l=newInterval.start;
        int r=newInterval.end;
        boolean insert=false;
        for(int i=0;i<len;i++){
            Interval tmp=intervals.get(i);
            if(tmp.start<=l&&tmp.end>=l)
                l=tmp.start;
            if(tmp.start<=r&&tmp.end>=r)
            {
                r=tmp.end;
                continue;
            }
            if(tmp.start>r&&!insert){
               res.add(new Interval(l,r));
               insert=true;
            }
            if(tmp.start>r||tmp.end<l)
               res.add(tmp);
        }
        if(!insert)
            res.add(new Interval(l,r));
        return res;
    }
}

8、无重复字符的最大字串:给定一个字符串,找出不含有重复字符的最长子串的长度

考察:哈希,ascii

class Solution {
    public int lengthOfLongestSubstring(String s) {
            int [] hash=new int[256];
        	Arrays.fill(hash, -1);
        	int maxLen=0,left=-1;
        	int len=s.length();
        	for(int i=0;i<len;i++){
        	   left=Math.max(left, hash[s.charAt(i)]);
        	   hash[s.charAt(i)]=i;
        	   maxLen=Math.max(maxLen, i-left);
        	}
            return maxLen;
    }
}

9、字符串转整数:实现 atoi,将字符串转为整数。

考察:指针遍历字符串的每个字符,math

class Solution {
    public int myAtoi(String str) {
        if(str.isEmpty())
            return 0;
        int flag=1,result=0,i=0,len=str.length();
        while(i<len&&str.charAt(i)==' ') i++;
        if(str.charAt(i)=='+'||str.charAt(i)=='-')
            flag=(str.charAt(i++)=='+')?1:-1;
        while(i<len&&str.charAt(i)>='0'&&str.charAt(i)<='9'){
            if(result>Integer.MAX_VALUE/10||(result==Integer.MAX_VALUE/10&&str.charAt(i)>'7'))
                return (flag==1)?Integer.MAX_VALUE:Integer.MIN_VALUE;
            result=result*10+(str.charAt(i++)-'0');
        }        
        return flag*result;
    }
}

10、三数之和:

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

考察:2个指针设定,排序

class Solution {

    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>>result=new LinkedList<>();
        int len=nums.length;
        Arrays.sort(nums);
        for(int i=0;i<len-2;i++){
            if(i>0&&nums[i]==nums[i-1])
                continue;
            int a=nums[i];
            int left=i+1;
            int right=len-1;
            while(left<right){
                if(left>i+1&&nums[left]==nums[left-1])
                    left++;
                else if(a+nums[left]+nums[right]>0){
                    right--;
                }
                else if(a+nums[left]+nums[right]<0){
                    left++;
                }
                else{
                    List<Integer>item=new LinkedList<>();
                    item.add(nums[i]);
                    item.add(nums[left]);
                    item.add(nums[right]);
                    result.add(item);
                    left++;
                    right--;
                }
            }
        }
        return result;
    }
}

11、有效的括号:

给定一个只包括 '('')''{''}''['']' 的字符串,判断字符串是否有效。

考察:栈

class Solution {
    public boolean isValid(String s) {
        LinkedList<Character> stack=new LinkedList<Character>();
        int len=s.length();
        for(int i=0;i<len;i++){
            Character c=s.charAt(i);
            if(c=='('||c=='{'||c=='['){
                stack.addFirst(c);
            }
            else{
                if(stack.isEmpty())
                    return false;
                Character top=stack.poll();
                if((c==')'&&top!='(')||(c=='}'&&top!='{')||(c==']'&&top!='['))
                    return false;
            }
        }
        return stack.isEmpty();
    }
}

 

13、合并两个有序链表:

将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

示例:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

考察:递归,归并思路

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode res=new ListNode(0);
        if(l1==null&&l2==null)
            return null;
        else if(l1!=null&&l2!=null){
            if(l1.val<l2.val){
                res.val=l1.val;
                res.next=mergeTwoLists(l1.next,l2);
            }
            else {
                res.val=l2.val;
                res.next=mergeTwoLists(l1,l2.next);
            }
        }
        else if(l1==null&&l2!=null){
            res.val=l2.val;
            res.next=l2.next;
        }
        else{
            res.val=l1.val;
            res.next=l1.next;
        }
        return res;
    }
}

2、两数相加:

 

给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。

你可以假设除了数字 0 之外,这两个数字都不会以零开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

考察:递归

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode add(ListNode l1,ListNode l2,int jin){
        if(l1==null&&l2==null&&jin==0)
            return null;
        if(l1==null)
            l1=new ListNode(0);
        if(l2==null)
            l2=new ListNode(0);
        ListNode res=new ListNode(0);
        int sum=l1.val+l2.val+jin;
        res.val=sum%10;
        res.next=add(l1.next,l2.next,sum/10);
        return res;
    }
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
       return add(l1,l2,0);
    }
}

15、Pow(x,n):

实现 pow(xn) ,即计算 x 的 n 次幂函数。

考察:分治,把线性复杂度将为logn

class Solution {
    public double myPow(double x, int n) {
        double res=1.0;
        if(x==0)
            return 0;
        else if(n==-1)
            return 1.0/x;
        else if(n==1)
            return x;
        else if(n==0)
            return 1.0;
        else {
            for(int i=n;i!=0;i/=2,x*=x){
                if(i%2!=0)
                    res*=x;
            }
            return n<0?1.0/res:res;
        }
        
    }
}

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章