蓝桥杯 自行车停放

题解

  • 题目没有解释清楚。不是最终的状态是恰好,而是每一次停放是恰好停放在其左边或者右边。
  • 另外,题目没有说明,应该是每一次需要停的车是x,已经停好的车是y。

综上,需要一个查找和插入都是O(1)复杂度的数据结构。—> hash +双向链表

实现

  • 使用顺序表记录链表的地址,从而实现O(1)的hash查找
  • 使用双向链表进行O(1)的插入

双向链表需要注意的点:

  1. 插入第一个结点的时候需要判断空
  2. 前插的时候,需要看是否插入第一个
    a. 如果是,不用指向自己
    b. 如果不是,头结点需要更新
  3. 向后插的时候,需要看是否插入最后一个,如果是,不用更新后一个的前结点。
  • cpp版本
//STl自行车停放
#include<bits/stdc++.h>
using namespace std;
long long n,x,a,b,c;
list<int> :: iterator loc[100003];
int main(){
    long long i; // 内存地址,使用long long 防止爆int
    list<int> L;
    cin>>n>>x;
    L.push_back(x); //把x插入
    loc[x] = L.begin(); //x的地址为链表的起始值
    list<int> :: iterator temp;
    for(int i=1;i<=n-1;i++){
        cin>>a>>b>>c; //a为代插元素,b为已有元素,c为方向
        temp = loc[b]; //b的地址给temp
        if(c==0){//左边插入
            L.insert(temp,a);
            loc[a] = --temp;
        }
        else{
            //右边插入
            L.insert(++temp,a);
            loc[a] =--temp;
        }
    }
for(list<int>::iterator it = L.begin() ; it!=L.end() ; it++)
cout << *it <<" ";
}
  • java实现

import java.io.*;
import java.lang.reflect.Array;
import java.util.*;

/**
 * @author: Zekun Fu
 * @date: 2022/12/19 23:45
 * @Description:
 */
public class Main{
    /**
     * 双向链表的实现
     *
     * @author liyanan
     * @date 2020/1/2 13:16
     */
    public static class SNode<T> {
        /**
         * 存储数据
         */
        public T data;
        /**
         * 指向当前结点的前一个结点
         */
        public SNode<T> pre;
        /**
         * 指向当前结点的下一个节点
         */
        public SNode<T> next;

        public SNode() {
        }

        public SNode(T data) {
            this.data = data;
        }
    }

    public static class DoubleLinkedList<T> {

        /**
         * 双向链表的头结点,存储第一个有效结点的基地址
         */
        private SNode<T> head;

        /**
         * 双向链表的有效结点数量
         */
        private int size;

        public DoubleLinkedList() {
            head = null;
            size = 0;
        }

        public int getSize() {
            return size;
        }


        public boolean isEmpty() {
            return size == 0;
        }

        /**
         * 插入结点到双向链表末尾
         *
         * @param newNode
         */
        public void addLast(SNode<T> newNode) {
            if (isEmpty()) {
                head = newNode;
                head.next = null;
                head.pre = null;
                size++;
            } else {
                SNode<T> temp = head;
                // 找到双向链表最后一个有效结点
                while (temp.next != null) {
                    temp = temp.next;
                }
                // 将新结点加入双向链表
                addAfter(temp, newNode);
            }
        }

        /**
         * 将新的节点插入到指定节点后
         *
         * @param preNode 指定节点
         * @param newNode 新的节点
         */
        public void addAfter(SNode<T> preNode, SNode<T> newNode) {
            // 要插入到链表末尾时,不需要维护下一个结点的前驱指针
            if (preNode.next != null) {
                preNode.next.pre = newNode;
            }
            newNode.next = preNode.next;
            newNode.pre = preNode;
            preNode.next = newNode;
            size++;
        }
        /**
         * 将结点插入到新结点前
         */
        public void addPre(SNode<T> afterNode, SNode<T> newNode) {
            // 要插入到链表第一个结点时候,不用维护前一个的后继
            if (afterNode.pre != null) {
                afterNode.pre.next = newNode;
            } else head = newNode;
            newNode.pre = afterNode.pre;
            newNode.next = afterNode;
            afterNode.pre = newNode;
            size++;
        }
        /**
         * 删除数据域为指定值的元素
         *
         * @param e
         */
        public void del(T e) {
            SNode<T> temp = head;
            while (temp != null) {
                if (temp.data.equals(e)) {
                    // 维护 head,head 永远指向双向链表第一个有效结点
                    temp.next.pre = temp.pre;
                    if (temp == head) {
                        head = head.next;
                        head.pre = null;
                    } else {
                        temp.pre.next = temp.next;
                    }
                    return;
                }
                // temp 向后移
                temp = temp.next;
            }
        }

        /**
         * 删除指定位置的结点
         *
         * @param k
         */
        public void del(int k) {
            SNode<T> delNode = find(k);
            delNode.next.pre = delNode.pre;
            if (delNode == head) {
                head = head.next;
                head.pre = null;
            } else {
                delNode.pre.next = delNode.next.next;
            }
        }

        public SNode<T> findO(T x) {
            SNode<T>p = head;
            while (p != null && !p.data.equals(x)) p = p.next;
            assert p != null;
            return p;
        }

        /**
         * 找到双向链表第 k 个结点
         *
         * @param k k 从 0 开始
         * @return
         */
        public SNode<T> find(int k) {
            if (k > size || k < 0) {
                throw new RuntimeException("传入的参数 k 必须大于等于零并且小于等于链表的长度 size");
            }
            int cnt = 0;
            SNode<T> t = head;
            while (cnt != k) {
                cnt++;
                t = t.next;
            }
            return t;
        }

        /**
         * 打印单链表所有有效节点
         *
         * @return
         */
        public String printAll() {
            StringBuilder sb = new StringBuilder();
            SNode<T> temp = head;
            while (temp != null) {
                sb.append(temp.data);
                sb.append(" ");
                temp = temp.next;
            }
            return sb.toString();
        }
    }
     public static void main(String[] args) throws Exception{
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
//        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
        HashMap<Integer, SNode<Integer>>loc = new HashMap<>();
        int n = Integer.parseInt(in.readLine());
        int x = Integer.parseInt(in.readLine());
        DoubleLinkedList<Integer> list = new DoubleLinkedList<>();
//        HashSet<Integer>set = new HashSet<>();
         SNode<Integer> cur = new SNode<>(x);
         loc.put(x, cur);
         list.addLast(cur);
        for (int i = 0; i < n - 1; i++) {
            String[] input = in.readLine().split(" ");
            int a = Integer.parseInt(input[0]);
            int b = Integer.parseInt(input[1]);
            int c = Integer.parseInt(input[2]);
            // b是已知结点,

            SNode<Integer> preNode = loc.get(b);
            cur = new SNode<>(a);
            loc.put(a, cur);
            if (c == 1) {
                // 把当前结点放在前一个结点的右边。
                list.addAfter(preNode, cur);
            }
            else {
                // 把当前结点放在前一个结点的左边
                list.addPre(preNode, cur);
            }
        }
//        out.write(list.printAll());
//         System.out.println();
        System.out.println(list.printAll());
    }
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
好的,以下是一个简单的 C 语言实现自行车停放问题的代码: ```c #include <stdio.h> #define MAX_BIKES 100 int main() { int n, m, i, j, bikes[MAX_BIKES], count = 0; printf("请输入停车场的容量和自行车的数量:\n"); scanf("%d %d", &n, &m); printf("请输入每辆自行车的停车位置:\n"); for (i = 0; i < m; i++) { scanf("%d", &bikes[i]); } // 模拟停车过程 for (i = 1; i <= n; i++) { // 找到空位并停车 for (j = 0; j < m; j++) { if (bikes[j] == i) { count++; bikes[j] = -1; // 标记已经停车 break; } } // 如果停车场已经满了,就停止停车 if (count == n) { break; } } // 统计剩余自行车的数量 int left = 0; for (i = 0; i < m; i++) { if (bikes[i] != -1) { left++; } } printf("停车场容量:%d,自行车数量:%d,剩余自行车数量:%d\n", n, m, left); return 0; } ``` 这个程序定义了一个整型数组 `bikes`,用于存储每辆自行车的停车位置。首先从用户输入中获取停车场的容量和自行车的数量,并且获取每辆自行车的停车位置。然后模拟停车过程:从位置 1 开始,依次找到第一个空位停车,直到停车场满了为止。在停车过程中,如果找到了可以停车的自行车,就将停车数量 `count` 加 1,并且将该自行车的位置标记为 -1,表示已经停车。停车完成后,统计剩余自行车的数量,输出停车场容量、自行车数量和剩余自行车数量。 需要注意的是,在实际情况中,停车场可能会出现自行车数量超过停车位的情况,此时需要进行额外处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值