蓝桥杯 2022 国赛 Java B组 左移右移

 

将数字序列中的某个值移动到序列的左/右端点,输出移动完成后的序列

第一时间想到的是用链表,我就直接用了Java内置的LinkedList,结果发现只能跑50%的测试用例。原因是链表结构的特点在于能快速插入与删除,但查询速度却不高。

查询其他人的做法,发现使用 双链表+哈希表 的组合,可以解决原来只使用链表时查询慢的问题

(个人做题经验并不多,第一次知道有这种组合操作,感叹真是妙啊~)

具体做法是用双链表的结点存储序列值,哈希表的K,V来存储序列值和对应的链表结点

这样一来,要对序列中的某个序列值进行操作时,就可以通过hashMap.get(序列值) 来获得对应的结点,也就知道了其前结点和后结点。有了这些信息,本题链表中删除某个结点的速度就会快上很多

Java代码如下

import java.util.HashMap;
import java.util.Scanner;

public class Main {

    static class Node { // 双链表的结点
        int value;
        Node pre;
        Node next;

        public Node(int value, Node pre, Node next) {
            this.value = value;
            this.pre = pre;
            this.next = next;
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();
        int m = sc.nextInt();

        HashMap<Integer, Node> map = new HashMap<>(); // 哈希表  用于快查

        // 完善双链表和哈希表
        Node head = new Node(-1, null, null);    //头结点
        Node tail = new Node(-1, null, null);    //尾结点
        Node point = head;    //指针,初始指向头结点
        for (int i = 1; i <= n; i++) {
            point.next = new Node(i, null, null); // point后插入新结点
            point.next.pre = point; // 新结点的前结点为当前指针
            point = point.next; // 更新point位置为新结点
            map.put(i, point);    //新结点放入哈希表
        }
        point.next = tail; // 最后一个结点的下一个结点为尾结点
        tail.pre = point; // 尾结点的前结点
        
        //输入指令
        char[] op = new char[m];
        int[] x = new int[m];
        for (int i = 0; i < m; i++) {
            op[i] = sc.next().charAt(0);
            x[i] = sc.nextInt();
        }
        sc.close();
        
        //执行指令
        for(int i=0 ; i<m ; i++) {
            //获取要操作的结点
            Node node = map.get(x[i]);
            //从原链表中取出这个结点
            node.next.pre = node.pre;
            node.pre.next = node.next;
            
            if(op[i]=='L') {
                //结点插入到链表头部
                node.next=head.next;
                node.pre=head;
                head.next=node;
                node.next.pre=node;
            }else if(op[i]=='R') {
                //结点插入到链表尾部
                node.pre=tail.pre;
                node.next=tail;
                tail.pre=node;
                node.pre.next=node;
            }
        }
        
        //输出结果
        point = head.next;
        while(point.value!= -1) {
            System.out.print(point.value+" ");
            point = point.next;
        }

    }

}

运行结果

最后再感叹一下,我是刷题菜鸟,第一次知道了 双链表+哈希表 这种组合用法,它能弥补单一数据结构自身的不足,真的很巧妙

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值