day1 3/3

215 数组中的第k个最大元素

剑指offer同样的题目

1.库函数排序
调用Arrays.sort()

class Solution {
    public int findKthLargest(int[] nums, int k) {
        Arrays.sort(nums);
        return nums[nums.length-k];
    }
}

时间复杂度o(nlogn)
空间复杂度o(1) : 原地排序,没有借助额外的辅助空间

2.快排中的partition函数
注意随机化pivot以避免极端测试用例
为了应对极端测试用例,使得递归树加深,可以在循环一开始的时候,随机交换第 1 个元素与它后面的任意1 个元素的位置;
说明:最极端的是顺序数组与倒序数组,此时递归树画出来是链表,时间复杂度是o(n^2),根本达不到减治的效果。
https://leetcode-cn.com/problems/kth-largest-element-in-an-array/solution/partitionfen-er-zhi-zhi-you-xian-dui-lie-java-dai-/

下次写代码注意 partition有两种方法可以实现!而且要记得使用random类随机化:
Random r = new Random()
该构造方法使用一个和当前系统时间对应的相对时间有关的数字作为种子数,然后使用这个种子数构造Random对象。

public Random(long seed)
该构造方法可以通过制定一个种子数进行创建。
示例代码:
Random r = new Random();
Random r1 = new Random(10);

public int nextInt(int n):是生成一个介于[0,n)的区间int值,包含0而不包含n

ps:若是相同种子数的Random对象,相同次数生成的随机数字是完全相同的。

本题中:int randomIndex = left + 1 + random.nextInt(right - left);

别人的代码写得更好 自己写的太慢了 也不好

时间复杂度o(n) 需要一些数学分析
空间复杂度o(1)

3.堆
https://leetcode-cn.com/problems/kth-largest-element-in-an-array/solution/partitionfen-er-zhi-zhi-you-xian-dui-lie-java-dai-/
可以运用实现好的堆
或者自己手写堆代码
没看 没写

31 下一个排列

不会写
非常清晰的思路:
https://leetcode-cn.com/problems/next-permutation/solution/xia-yi-ge-pai-lie-suan-fa-xiang-jie-si-lu-tui-dao-/
先举一个简单的例子 123456 再举一个稍微复杂的例子 123465
照着思路写的代码

class Solution {
    public void nextPermutation(int[] nums) {
        int index=-1;
        for(int i=nums.length-1;i>0;i--){
            if(nums[i]>nums[i-1]){
                index=i;
                break;
            }
        }
        if(index!=-1){
            for(int i=nums.length-1;i>=index && index!=-1;i--){
                if(nums[i]>nums[index-1]){
                    int temp=nums[i];
                    nums[i]=nums[index-1];
                    nums[index-1]=temp;
                    break;
                }
            }
            Arrays.sort(nums,index,nums.length);
        }
        else{
            Arrays.sort(nums);
        }
    }
}

其实不用设置index,不用在意如果本身就是最大字典序的情况
如下

class Solution {
    public void nextPermutation(int[] nums) {
        int len = nums.length;
        for (int i = len - 1; i > 0; i--) {
                if (nums[i] > nums[i - 1]) {
                    Arrays.sort(nums, i, len);
                    for (int j = i; j <len; j++) {
                        if (nums[j] > nums[i - 1]) {
                            int temp = nums[j];
                            nums[j] = nums[i - 1];
                            nums[i - 1] = temp;
                            return;
                        }
                    }
                }
            }
        Arrays.sort(nums);
        return;  
    }
 }

55 跳跃游戏

思路1:dfs
遍历每一条路径,只要找到一条可以到达最后一个下标,那就直接结束dfs。
可惜TLE

class Solution {
    public boolean canJump(int[] nums) {
        return dfs(nums,0);
    }

    boolean dfs(int[] nums,int index){
        int len=nums[index];
        //错误代码
        // if(len==0){
        //     return false;
        // }
        // else if(index==nums.length-1){
        //     return true;
        // }

        //注意顺序
        //特殊的case [0] 是可以到达末端的。
        //而且到达末端了,最后一个下标的可跳跃长度是0也可以,因为我已经到达了!!!
        if(index==nums.length-1){
            return true;
        }
        else if(len==0){
            return false;
        }
        //如果找到一条成功的就直接return
        boolean flag=false;
        for(int i=len;i>0&&!flag;i--){
            if(index+i>nums.length-1) continue;
            flag=dfs(nums,index+i);
        }
        return flag;
    }
}

利用vistied记录,勉强通过5% 5%

class Solution {
    public boolean canJump(int[] nums) {
        boolean[] visited=new boolean[nums.length];
        return dfs(nums,0,visited);
    }

    boolean dfs(int[] nums,int index,boolean[] visited){
        int len=nums[index];
        if(index==nums.length-1){
            return true;
        }
        else if(len==0){
            return false;
        }
        else if(visited[index]) return false;
        //如果找到一条成功的就直接return
        boolean flag=false;
        for(int i=len;i>0&&!flag;i--){
            if(index+i>nums.length-1) continue;
            flag=dfs(nums,index+i,visited);
        }
        visited[index]=true;
        return flag;
    }
}

思路2:贪心 尽可能到达越远的位置
解题思路:
如果某一个作为 起跳点 的格子可以跳跃的距离是 3,那么表示后面 3 个格子都可以作为 起跳点。
重点在于 - 遍历的同时更新所能跳到的最远距离:对每一个能作为 起跳点 的格子都尝试跳一次,把 能跳到最远的距离不断更新。

即:初始化最远位置为 0,然后遍历数组,如果当前位置能到达,并且当前位置+跳数>最远位置,就更新最远位置。最后比较最远位置和数组长度。

class Solution {
    public boolean canJump(int[] nums) {
        int k=0;
        for(int i=0;i<nums.length;i++){
            if(k<i) return false;
            k=Math.max(k,i+nums[i]);
        }
        return true;
    }
}

优化一下

class Solution {
    public boolean canJump(int[] nums) {
        int k=0;
        for(int i=0;i<nums.length;i++){
            if(k<i) return false;
            k=Math.max(k,i+nums[i]);
            if(k>=nums.length-1) return true;
        }
        return true;
    }
}

时间复杂度 O(n),空间复杂度 O(1)

114 二叉树展开为链表

对于二叉树的题目,无非就以下几种解题思路:
先序遍历(深度优先搜索)
中序遍历(深度优先搜索)(尤其二叉搜索树)
后序遍历(深度优先搜索)
层序遍历(广度优先搜索)(尤其按照层来解决问题的时候)
序列化与反序列化(结构唯一性问题)
根据我们的观察,本题应该是使用深度优先搜索的方式来解决

思路1:
(题目提示说如果可以就原地展开,才突然想到可以利用辅助内存)
先序遍历二叉树,利用队列保存每一个节点的地址。
然后再从根节点修改指针的指向。

但是注意,这道题不可以新建结点来构造链表。因为题目的原意就是改造原二叉树为一个链表。直接在原来的节点上改变指向。
”给你二叉树的根结点 root ,请你将它展开为一个单链表“

class Solution {
    public void flatten(TreeNode root) {
        Queue<TreeNode> tree = new LinkedList<TreeNode>();
        dfs(root,tree);
        if(tree.size()>=1) tree.poll();
        while(tree.size()>0){
            root.right=tree.peek();
            root.left=null;
            tree.poll();
            root=root.right;
        }
    }
    void dfs(TreeNode root,Queue<TreeNode> tree){
        if(root==null){
            return ;
        }
        tree.offer(root);
        dfs(root.left,tree);
        dfs(root.right,tree);
    }
}

利用数组保存每一个节点的值

class Solution {
    public void flatten(TreeNode root) {
        List<TreeNode> list = new ArrayList<TreeNode>();
        preorderTraversal(root, list);
        int size = list.size();
        for (int i = 1; i < size; i++) {
            TreeNode prev = list.get(i - 1), curr = list.get(i);
            prev.left = null;
            prev.right = curr;
        }
    }

    public void preorderTraversal(TreeNode root, List<TreeNode> list) {
        if (root != null) {
            list.add(root);
            preorderTraversal(root.left, list);
            preorderTraversal(root.right, list);
        }
    }
}

非递归写法,没有理解与实现
涉及到的知识点:# 二叉树的遍历:先序中序后序遍历的递归与非递归实现及层序遍历

class Solution {
    public void flatten(TreeNode root) {
        List<TreeNode> list = new ArrayList<TreeNode>();
        Deque<TreeNode> stack = new LinkedList<TreeNode>();
        //双端队列 继承自queue
        TreeNode node = root;
        while (node != null || !stack.isEmpty()) {
            while (node != null) {
                list.add(node);
                stack.push(node);
                node = node.left;
            }
            node = stack.pop();
            node = node.right;
        }
        int size = list.size();
        for (int i = 1; i < size; i++) {
            TreeNode prev = list.get(i - 1), curr = list.get(i);
            prev.left = null;
            prev.right = curr;
        }
    }
}

时间复杂度空间复杂度 o(n)
思路2:原地展开 空间复杂度o(1)
https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/solution/114-er-cha-shu-zhan-kai-wei-lian-biao-by-ming-zhi-/
超级棒
其实是后序遍历:在还没操作节点右子树前,不能破坏该节点的右子树指向。所以采用后序遍历。

class Solution {
    public void flatten(TreeNode root) {
        if(root == null){
            return ;
        }
        //将根节点的左子树变成链表
        flatten(root.left);
        //将根节点的右子树变成链表
        flatten(root.right);
        TreeNode temp = root.right;
        //把树的右边换成左边的链表
        root.right = root.left;
        //记得要将左边置空
        root.left = null;
        //找到树的最右边的节点
        while(root.right != null) root = root.right;
        //把右边的链表接到刚才树的最右边的节点
        root.right = temp;
    }
}

非递归写法:

class Solution {
    public void flatten(TreeNode root) {
        Stack<TreeNode> stack = new Stack();
        while (root != null || !stack.isEmpty()){
            while (root != null){
                stack.push(root);
                root = root.left;
            }

            if (!stack.isEmpty()){
                TreeNode node = stack.pop();
                TreeNode tmp = node.right;
                node.right = node.left;
                node.left = null;
                
                while(node.right != null) node = node.right;
                node.right = tmp;
                root = tmp;
            }
        }
    }
}

思考为什么要用后序遍历?
看看:
https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by--26/
(解法2、3)

https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/solution/er-cha-shu-zhan-kai-wei-lian-biao-by-leetcode-solu/

https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/solution/biao-biao-zhun-zhun-de-hou-xu-bian-li-dai-ma-jian-/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容