算法准备-4.14

算法准备-4.14

1.复杂链表的复制

  1. 描述:请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null

  2. 思路:分三步,第一步复制每个节点使其位于原节点的后面;第二步建立random指针;第三步恢复链表

  3. 题解:

    /*
    // Definition for a Node.
    class Node {
        int val;
        Node next;
        Node random;
    
        public Node(int val) {
            this.val = val;
            this.next = null;
            this.random = null;
        }
    }
    */
    class Solution {
        public Node copyRandomList(Node head) {
            if(head==null)
            {
                return null;
            }
            copy(head);
            random(head);
            return reList(head);
        }
        private void copy(Node head){//保证每个节点在原节点的后面
            while(head!=null)
            {
                    Node clonenode=new Node(head.val);
                    Node headnext=head.next;
                    head.next=clonenode;
                    clonenode.next=headnext;
                    head=clonenode.next;
            }
        }
        private void random(Node head){
            while(head!=null)
            {
                while(head!=null){
                Node cloneNode = head.next;
                if(head.random!=null){
                    head.next.random = head.random.next;
                }
                head = cloneNode.next;
            }
            }
        }
        private Node reList(Node head)
        {
            Node clonehead=head.next;
            Node clonenode=head.next;
            head.next=clonenode.next;
            head=head.next;
            while(head!=null)
            {
                clonenode.next=head.next;
                head.next=head.next.next;
                head=head.next;
                clonenode=clonenode.next;
            }
            return clonehead;
        }
    }
    

2. 二叉搜索树转有序双向链表

  1. 描述:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向

  2. 思路:首先,因为链表有序,所以我们必须通过中序遍历来访问二叉搜索树,来得到一个有序的访问序列,其次因为他不能创建新的节点,只能改变树中的指针指向,其左指针指向前驱,右指针指向后继,当结束后,再将最后一个节点的后继指针指向head指向的结点。

  3. 题解:

    /*
    // Definition for a Node.
    class Node {
        public int val;
        public Node left;
        public Node right;
    
        public Node() {}
    
        public Node(int _val) {
            val = _val;
        }
    
        public Node(int _val,Node _left,Node _right) {
            val = _val;
            left = _left;
            right = _right;
        }
    };
    */
    class Solution {
        Node head,pre;//伪头节点和前驱指针节点
        public Node treeToDoublyList(Node root) {
            if(root==null)
            {
                return null;
            }
            dfs(root);
            head.left=pre;
            pre.right=head;
            return head;
        }
        public void dfs(Node root){//中序遍历二叉搜索树同时改变指针
            if(root==null)
            {
                return;
            }
            dfs(root.left);
            if(pre!=null) pre.right=root;
            else head=root;//判断他是否是第一个节点
            root.left=pre;
            pre=root;
            dfs(root.right);
        }
    }
    
    

3. 字符串的排列

  1. 描述:输入一个字符串,打印出该字符串中字符的所有排列

  2. 思路:此题采用DFS加剪枝,对字符串进行深度优先搜索遍历,要保证同一位置上同意字符只能固定一次,需要建立一个字符数组做对比。

  3. 题解:

    class Solution {
        List<String> res=new LinkedList<>();
        char[] target;
        public String[] permutation(String s) {
            target=s.toCharArray();
            dfs(0);
            return res.toArray(new String[res.size()]);
        }
        public void dfs(int x){
            if(x==target.length-1)
            {
                res.add(String.valueOf(target));
                return;
            }
            HashSet<Character> set = new HashSet<>();//进行重复检验
            for(int i=x;i<target.length;i++)
            {
                if(set.contains(target[i])) continue;
                set.add(target[i]);
                swap(i,x);
                dfs(x+1);
                swap(i,x);
            }
        }
        public void swap(int a,int b){
            char temp=target[a];
            target[a]=target[b];
            target[b]=temp;
        }
    }
    
  4. 反省:这题是参考了leetcode讨论区一位大佬的做法,一开始我不知道这题要用dfs,回溯加剪枝,剪枝时使用的hashset也没用过

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值