1.4.1 链表荷兰国旗问题,链表交叉,随机链表复制问题

3. 左右两侧链表,变成交叉链表

a -> b -> c -> 1 -> 2 -> 3 变成 a -> 1 -> b -> 2 -> c -> 3 结构,奇数中点变成最后一个


    // 左右两侧链表,变成交叉链表
    public void crossLink(Node head) {
        if (head == null || head.next == null) {
            return;
        }
        Node end = getMiddle(head, 0);
        Node start = end.next;
        // 变成两个链表织入问题
        end.next = null;
        Node next, startNext;
        while (head != null) {
            next = head.next;
            head.next = start;
            head = next;
            if (start == null) {
                return;
            }
            startNext = start.next;
            start.next = head;
            start = startNext;
        }
    }

    public void crossLinkCompare(Node head) {
        if (head == null) {
            return;
        }
        List<Node> list = new ArrayList<>();
        while (head != null) {
            list.add(head);
            head = head.next;
        }
        int N = list.size(), end = N / 2 - (N + 1) % 2, end0;
        int i = 0;
        for (; i < end; i++) {
            end0 = end + i + 1;
            list.get(i).next = list.get(end0);
            list.get(end0).next = list.get(i + 1);
        }
        // 偶数,对尾节点进行单独考虑
        if (N % 2 == 0) {
            list.get(i).next = list.get(N - 1);
        } else {
            list.get(N - 1).next = list.get(i);
            list.get(i).next = null;
        }
    }

    @Test
    public void test4() {
        for (int i = 0; i < 1000; i++) {
            Node node = Reduce.link(10, 100);
            Node node1 = Reduce.copy(node);
            Node node2 = Reduce.copy(node);
            crossLink(node1);
            crossLinkCompare(node2);
            if (!CompareUtil.compare(node1, node2)) {
                System.out.println(Printer.print(node));
                System.out.println(Printer.print(node1));
                System.out.println(Printer.print(node2));
                return;
            }
        }
    }

4. 给一个链表,和一个常数 V,使 < V 的在左侧,=V的在中间,> V 的在右侧

使用6个指针,分别是 小于,等于,大于 区的开始结束指针

    // 给一个链表,和一个常数 V,使 < V 的在左侧,=V的在中间,> V 的在右侧
    public Node partitionLink(Node node, int value) {
        if (node == null) {
            return null;
        }
        Node lessValueStart = null, lessValueEnd = null;
        Node equalValueStart = null, equalValueEnd = null;
        Node greaterValueStart = null, greaterValueEnd = null;
        while (node != null) {
            if (node.value < value) {
                if (lessValueStart == null) {
                    lessValueStart = node;
                    lessValueEnd = node;
                } else {
                    lessValueEnd.next = node;
                    lessValueEnd = node;
                }
            } else if (node.value == value) {
                if (equalValueStart == null) {
                    equalValueStart = node;
                    equalValueEnd = node;
                } else {
                    equalValueEnd.next = node;
                    equalValueEnd = node;
                }
            } else {
                if (greaterValueStart == null) {
                    greaterValueStart = node;
                    greaterValueEnd = node;
                } else {
                    greaterValueEnd.next = node;
                    greaterValueEnd = node;
                }
            }
            node = node.next;
        }
        Node head1 = null, end = null;
        if (lessValueStart != null) {
            head1 = lessValueStart;
            end = lessValueEnd;
        }
        if (equalValueStart != null) {
            if (head1 != null) {
                end.next = equalValueStart;
            } else {
                head1 = equalValueStart;
            }
            end = equalValueEnd;
        }
        if (greaterValueStart != null) {
            if (head1 == null) {
                head1 = greaterValueStart;
            } else {
                end.next = greaterValueStart;
            }
            end = greaterValueEnd;
        }
        end.next = null;
        return head1;
    }

    public Node partitionLinkCompare(Node node, int value) {
        if (node == null || node.next == null) {
            return node;
        }
        List<Node> list = new ArrayList<>();
        while (node != null) {
            list.add(node);
            node = node.next;
        }
        int less = 0, grater = list.size() - 1, i = 0;
        while (i <= grater) {
            int v = list.get(i).value;
            if (v < value) {
                swap(list, i++, less++);
            } else if (v > value) {
                swap(list, i, grater--);
            } else {
                swap(list, i++, less);
            }
        }
        for (int j = 1; j < list.size(); j++) {
            list.get(j - 1).next = list.get(j);
        }
        list.get(list.size() - 1).next = null;
        return list.get(0);
    }

    private void swap(List<Node> list, int i, int j) {
        Node temp = list.get(i);
        list.set(i, list.get(j));
        list.set(j, temp);
    }

    public boolean valid(Node node, int value) {
        int i = 0, t;
        while (node != null) {
            t = node.value < value ? 1 : node.value == value ? 2 : 3;
            if (i > t) {
                return false;
            }
            i = t;
            node = node.next;
        }
        return true;
    }

    @Test
    public void test6() {
        for (int i = 0; i < 10000; i++) {
            Node node = Reduce.link(10, 100);
            Node node1 = Reduce.copy(node);
            Node node2 = Reduce.copy(node);
            int value = Reduce.num(-100, 100);
            Node n1 = partitionLink(node1, value);
            Node n2 = partitionLinkCompare(node2, value);
            if (!valid(n1, value) || !valid(n2, value)) {
                System.out.println(value);
                System.out.println(Printer.print(node));
                System.out.println(Printer.print(n1));
                System.out.println(Printer.print(n2));
                return;
            }
        }
    }

5. 复制一个链表,每一个节点有 next,random


    // 基本思路是,先复制一个相同节点,连在 node后
    public RandomNode copyRandomNode(RandomNode node) {
        if (node == null) {
            return null;
        }
        RandomNode curr1, curr = node;
        RandomNode temp;
        while (curr != null) {
            curr1 = new RandomNode(curr.value);
            temp = curr.next;
            curr.next = curr1;
            curr1.next = temp;
            curr = temp;
        }
        RandomNode res = node.next;
        curr = node;
        while (curr != null) {
            curr.next.random = curr.random == null ? null : curr.random.next;
            curr.next = curr.next.next;
            curr = curr.next;
        }
        return res;
    }

    public RandomNode copyRandomNodeCompare(RandomNode node) {
        Map<RandomNode, RandomNode> map = new HashMap<>();
        RandomNode curr = node;
        while (curr != null) {
            map.put(curr, new RandomNode(curr.value));
            curr = curr.next;
        }
        curr = node;
        while (curr != null) {
            map.get(curr).next = map.get(curr.next);
            map.get(curr).random = curr.random == null ? null : map.get(curr.random);
            curr = curr.next;
        }
        return map.get(node);
    }

    @Test
    public void test7() {
        for (int i = 0; i < 1000; i++) {
            RandomNode node = Reduce.randomNode(5, 100);
            RandomNode node1 = copyRandomNode(node);
            RandomNode node2 = copyRandomNodeCompare(node);
            if (!CompareUtil.compare(node1, node2)) {
                System.out.println(Printer.print(node));
                System.out.println(Printer.print(node1));
                System.out.println(Printer.print(node2));
                return;
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值