leetcode 刷题系列(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Viscu/article/details/82226851

230. 二叉搜索树中第K小的元素

给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。
说明:
你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。
示例 1:

输入: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2
输出: 1
示例 2:
输入: root = [5,3,6,2,4,null,null,1], k = 3
       5
      / \
     3   6
    / \
   2   4
  /
 1
输出: 3

思路:根据中序遍历,bst是升序的,那么我们用一个st记录该节点的走过的第几个节点,当等于k即可第k小的答案。

class Solution {
    private int st;
    private int ans;
    private boolean flag;
    public int kthSmallest(TreeNode root, int k) {
        st=0;
        flag=false;
        ans=-1;
        dfs(root,k);
        return ans;
    }
    public void dfs(TreeNode root,int k){
        if(root==null||flag){
            return;
        }
        if(root.left!=null){
            dfs(root.left,k);
        }
        if(++st==k){
            ans=root.val;
            flag=true;
        }
        if(root.right!=null){
            dfs(root.right,k);
        }
    }
}
449. 序列化和反序列化二叉搜索树

序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。
设计一个算法来序列化和反序列化二叉搜索树。 对序列化/反序列化算法的工作方式没有限制。 您只需确保二叉搜索树可以序列化为字符串,并且可以将该字符串反序列化为最初的二叉搜索树。
编码的字符串应尽可能紧凑。
注意:不要使用类成员/全局/静态变量来存储状态。 你的序列化和反序列化算法应该是无状态的。

思路:利用前序遍历(前序遍历可以保持原来的树结构)遍历整棵BST.其中我们用 ’ ‘表示该节点val值的终点标志,用#表示空树,dfs一遍即可。

class Codec2 {
    public int pos;
    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        if(root==null){
            return "#";
        }
        StringBuilder sb=new StringBuilder();
        sb.append(root.val);
        sb.append(' ');
        sb.append(serialize(root.left));
        sb.append(serialize(root.right));
        return sb.toString();
    }
    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        pos=0;
        return dfs(data);
    }
    public TreeNode dfs(String data){
        if(data.charAt(pos)=='#'){
            ++pos;
            return null;
        }
        int val=0;
        while (data.charAt(pos)!=' '){
            val=val*10+(data.charAt(pos)-'0');
            ++pos;
        }
        ++pos;
        TreeNode root=new TreeNode(val);
        root.left=dfs(data);
        root.right=dfs(data);
        return root;
    }
    public static void main(String[] args) {
        TreeNode root=new TreeNode(2);
        root.left=new TreeNode(1);
        root.right=new TreeNode(3);
        String s=new Codec2().serialize(root);
        TreeNode r=new Codec2().deserialize(s);
    }
}
450. 删除二叉搜索树中的节点
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

一般来说,删除节点可分为两个步骤:

首先找到需要删除的节点;
如果找到了,删除它。
说明: 要求算法时间复杂度为 O(h),h 为树的高度。

示例:

root = [5,3,6,2,4,null,7]
key = 3

    5
   / \
  3   6
 / \   \
2   4   7

给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。

一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。

    5
   / \
  4   6
 /     \
2       7

另一个正确答案是 [5,2,6,null,4,null,7]。

    5
   / \
  2   6
   \   \
    4   7

若要删除一个BST的一个结点,需要考虑如下三种情况:
需要删除的节点下并没有其他子节点
需要删除的节点下有一个子节点(左或右)
需要删除的节点下有两个子节点(既左右节点都存在)
对这三种情况分别采取的措施是:
直接删除此结点
删除此结点,将此结点父节点连接到此结点左(右)子树
找出此结点右子树中的最小结点,用以代替要删除的结点,然后删除此最小结点(或者右子树的最大节点,即第二种情况)

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        return dfs(root,key);
    }
    public TreeNode dfs(TreeNode root,int key){
        if(root==null){
            return null;
        }
        if(key<root.val){
            root.left=dfs(root.left,key);
        }else if(key>root.val){
            root.right=dfs(root.right,key);
        }else{
            if(root.left==null||root.right==null){ // 存在至多一个子节点
                root=(root.left==null)?root.right:root.left;
            }else{ //两个子节点都存在
                TreeNode cur=root.right;
                while (cur.left!=null){ 
                    cur=cur.left;
                }
                root.val=cur.val;
                root.right=deleteNode(root.right,cur.val);        
            }
        }
        return root;
    }
}
329. 矩阵中的最长递增路径

给定一个整数矩阵,找出最长递增路径的长度。
对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。

记忆化搜索,我们记录下每次走过的点,由该点延伸出去的能走最大的长度。
然后枚举矩阵所有的点,找出最长的路径。之前走过的状态都保留着,
所以越到后面的dfs就可以直接得出答案。

class Solution {
    int[] dx={0,0,1,-1};
    int[] dy={1,-1,0,0};
    boolean[][] vis;
    int n,m;
    int[][] path;
    public int longestIncreasingPath(int[][] matrix) {
        if(matrix.length==0||matrix[0].length==0){
            return 0;
        }
        int ans=0;
        n=matrix.length;
        m=matrix[0].length;
        vis=new boolean[n][m];
        path=new int[n][m];
        for(int i=0;i<n;++i){
            for(int j=0;j<m;++j){
                ans=Math.max(dfs(i,j,matrix,path),ans);
            }
        }
        return ans;
    }
    boolean check(int x,int y){
        if(x<0||y<0||x>=n||y>=m){
            return false;
        }
        return true;
    }
    //保留路径的长度
    public int dfs(int x,int y,int[][] matrix,int[][] path){
        if(vis[x][y]){
            return path[x][y];
        }
        path[x][y]=1;
        for(int i=0;i<4;++i){
            int xi=x+dx[i];
            int yi=y+dy[i];
            if(check(xi,yi)&&matrix[xi][yi]<matrix[x][y]){
                path[x][y]=Math.max(path[x][y],dfs(x+dx[i],y+dy[i],matrix,path)+1);
            }
        }
        vis[x][y]=true;
        return path[x][y];
    }
}

160. 相交链表

题目描述提示帮助提交记录社区讨论阅读解答
随机一题
编写一个程序,找到两个单链表相交的起始节点。
例如,下面的两个链表:
A: a1 → a2

c1 → c2 → c3

B: b1 → b2 → b3
在节点 c1 开始相交。
注意:
如果两个链表没有交点,返回 null.
在返回结果后,两个链表仍须保持原有的结构。
可假定整个链表结构中没有循环。
程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

  • 先记录a,b的长度la,lb,且记录a,b的最后一个节点,若相等,相交。
  • 让长(假设la长)的链表先走la-lb步,再同一起走,知道curA==curB,即为相交节点。
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA==null||headB==null){
            return null;
        }
        int lenA=1;
        ListNode curA=headA;
        while (curA.next!=null){
            ++lenA;
            curA=curA.next;
        }
        int lenB=1;
        ListNode curB=headB;
        while (curB.next!=null){
            ++lenB;
            curB=curB.next;
        }
        if(curA!=curB){
            return null;
        }
        curA=headA;
        curB=headB;
        int t;
        if(lenA>lenB){
            t=lenA-lenB;
            while (--t>=0){
                curA=curA.next;
            }
        }else{
            t=lenB-lenA;
            while (--t>=0){
                curB=curB.next;
            }
        }
        while (true){
            if(curA==curB){
                return curA;
            }else{
                curA=curA.next;
                curB=curB.next;
            }
        }
    }
}

14. 最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。

以第一个串为外循环,记录匹配的最后一个位置,暴力即可。

class Solution {
    public String longestCommonPrefix(String[] strs) {
        if(strs.length==0){
            return "";
        }
        int i,j;
        int lsindx=0;
        for(i=0;i<strs[0].length();++i){
            for(j=1;j<strs.length;++j){
                if((strs[j].length()-1)<i||strs[j].charAt(i)!=strs[0].charAt(i)){
                    break;
                }
            }
            if(j!=strs.length){
                return strs[0].substring(0,i);
            }else{
                lsindx=i+1;
            }
        }
        return strs[0].substring(0,lsindx);
    }
}
22. 括号生成

给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
例如,给出 n = 3,生成结果为:
[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]

思路:dfs即可。l代表可以添加多少个’(‘,r代表可以添加多少个’)’.
注意一下添加”)”的条件即可,添加“)”必须是前面已经有“(”才可以添加,判断条件就是r!=0&&r>l.

class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> ans=new ArrayList<String>();
        dfs(n,n,ans,"");
        return ans;
    }
    public void dfs(int l,int r,List<String> ans,String s){
        if(l==0&&r==0){
            ans.add(s);
            return;
        }
        if(l!=0){
            dfs(l-1,r,ans,s+"(");
        }
        if(r!=0&&r>l){
            dfs(l,r-1,ans,s+")");
        }
    }
}

67. 二进制求和

模拟即可。

class Solution {
    public String addBinary(String a, String b) {
        if(a==null||b==null){
            return a==null?b:a;
        }
        StringBuilder sb=new StringBuilder();
        int m=a.length();
        int n=b.length();
        if(m<n){
            String tmp=b;
            b=a;
            a=tmp;
        }
        int t=Math.abs(m-n);
        int ex=0;
        int ad;
        for(int i=a.length()-1;i>=0;--i){
            if(i-t>=0){
                ad=a.charAt(i)-'0'+b.charAt(i-t)-'0'+ex;
            }else{
                ad=a.charAt(i)-'0'+ex;
            }
            if(ad>=2){
                sb.append(ad%2);
                ex=1;
            }else{
                sb.append(ad);
                ex=0;
            }
        }
        if(ex==1){
            sb.append(1);
        }
        return sb.reverse().toString();
    }
}   

猜你喜欢

转载自blog.csdn.net/Viscu/article/details/82226851