一个算法题引发的血案_(´ཀ`」 ∠)_(不是

博主分享了一次遭遇复杂算法题的经历,原本以为是简单的蓝桥杯水题,却发现题目规模增大了100倍。在尝试Java和Go语言后遇到超时问题,最终通过实现优先队列解决。虽然C++解决方案更简洁,但Go语言中实现优先队列较为繁琐。尽管成功解决,却错过了干饭时间,而同伴已放弃这道题,直呼麻烦。
摘要由CSDN通过智能技术生成

这是一个令人开(吐)心(血)的故事在这里插入图片描述
今天早上,我本来开开心心的在日常摸鱼。
突然“一代赌王”(外号之一)妹子发来了一道算法题

我见过它,新建文档,很普通的一道蓝桥算法题嘛,虽然咱技术很渣,但跟妹子做一道基础水题应该还是没什么难度的




…吧

打开这个算法所在的竞赛,位置很靠前,

感觉更有信心了.....呢(变音)?
这个提交通过率好像有点不对啊
在这里插入图片描述

惴惴不安的我点开页面,查看问题描述,嗯确实是那道水题,直接开整!!

在这里插入图片描述
解析题目,哎呀,不就是队列记录新建与文件状态吗,遍历维护一个数组就行了

import java.util.Scanner;
 
public class Main {
 
	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		Scanner scanner = new Scanner(System.in);
		int[] arr = new int[100000];
		int n = scanner.nextInt();
		for(int i=0;i<n;i++){
			String string = scanner.next();
			if(string.charAt(0)=='N'){//New
				for(int j=0;j<n;j++){
					if(arr[j]==0){
						arr[j]=1;
						System.out.println(j+1);
						break;
					}
				}
			}else{//Delete
				int a = scanner.nextInt();
				if(arr[a-1]==1){
					arr[a-1]=0;
					System.out.println("Successful");
				}else if(arr[a-1]==0){
					System.out.println("Failed");
				}
			}
		}
	}
}

欧了!结束战斗

一运行 嗯.~~?!

在这里插入图片描述
超时???,什么鬼?

我的java很菜啊,于是火速换了go语言,用一个切片来存储被删除的文档下标,然后对其排序。
package main
 
import "fmt"
 
func SortSlice(slice []int) {
    for i := 0; i < len(slice)-1; i++ {
        //遍历i位以后的所有元素,如果比i位元素小,就和i位元素互换位置
        for j:=i+1;j<len(slice) ;j++  {
            if slice[j] < slice[i]{
                slice[i],slice[j] = slice[j],slice[i]
            }
        }
    }
}
 
func main()  {
    var a [100001]int
    var str string
    aa := make([]int, 0, 100)
    n,t:=0,0
    j:=1
    for  {
        c,_ :=fmt.Scan(&n)
        if c==0{
        break
        }else{
            for i:=1;i<=n;i++{
                fmt.Scan(&str)
                if str=="New"{
                    if len(aa)>0{
                        le :=len(aa)
                        if le == 1 {
                            a[aa[0]]=1
                            fmt.Println(aa[0])
                            aa=[]int{}
                        }else {
                            SortSlice(aa)
                            a[aa[0]]=1
                            fmt.Println(aa[0])
                            aa = append(aa[:0], aa[1:]...)
                        }
                    }else {
                        a[j]=1
                        fmt.Println(j)
                        j++
                    }
                }else {
                    fmt.Scan(&t)
                    if a[t]==1{
                        a[t]=0
                        aa = append(aa,t)
                        fmt.Println("Successful")
                    }else {
                        fmt.Println("Failed")
                         
                        }
                }
            }
            break
        }
    }
}

然后…
在这里插入图片描述

这什么鬼??,在次审视这个题
然后我发现
淦!
它比蓝桥杯的水题增加了100倍,100000次操作在这里插入图片描述
请添加图片描述
这玩意一搞,顿时心态全无,怪不得通过率这么诡异。
看了看其他小伙伴的代码什么c,python,C++写的都不。。。嗯???C++???在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

为什么它怎么优秀?
仔细看了一下代码

priority_queue<int> que;
const int SIZE = 1e6 + 7;
bool Vis[SIZE]; int cnt;

好家伙
优先队列!!
原来是你小子
通过优先队列对存储的删除下标排序,在新建时首先对队列pop,既可以实现要求,又能完美免去一层遍历。
妙啊!!

but,
我们的妹子用的是GO
而咱GO是没有对象的!!!
啊,
不是,
是没有优先队列的。
所以麻烦的来了,我还得自己先实现一个
一般情况下讲,我可以使用priority queue实现优先级队列
但是我这个网络吧
请添加图片描述
大锅这话非常贴切

而且,Y(ya,一声,一种语气词)导包,牛客上也运行不了啊
所以莫得办法,只能依靠Heap来实现一个了

package main

import (
	"container/heap"
	"fmt"
	"strconv"
)

// QItem 表示存储到这个队列中需要实现的接口
type QItem interface {
	//QItem接口要实现的方法,要求接收的变量是QItem类型,返回值为bool
	Less(item QItem) bool

}

/*
priorityQueueImpl 用于优先队列底层实现,
优先队列涉及两部分,数据排序与数据压入弹出pop和push,也就是Heap包中的几个方法,
Heap基于接口实现,所以我们可以通过实现两个接口的基础方法去嵌套继承两个方法
声明一个[]QItem类型的类型别名为priorityQueueImpl
这里我们的priorityQueueImpl实际上就是实现了heap
*/
type priorityQueueImpl []QItem
// 下面实际上是实现了一个[]QItem类型的的Head方法
// Len 获取队列长度,为priorityQueueImpl类型实现len方法,返回值为int
func (pqi priorityQueueImpl) Len() int {
	return len(pqi)
}
/*
	Less方法 用来进行元素比较
	为priorityQueueImpl类型实现less方法,实现QItem接口
	priorityQueueImpl类型本质上还是数组,传入的i,j作为下标
	返回的是比对结果的布尔值
	因为我们实现了Less,Swap,Len这三个方法,
	因此priorityQueueImpl就实现了Interface接口
*/
func (pqi priorityQueueImpl) Less(i, j int) bool {
	/*
	这里左侧点进去可以见到sort
	这里的less是拿的实现该方法的priorityQueueImpl实例的less方法
	*/
	return pqi[i].Less(pqi[j])
}

// Swap 进行交换
func (pqi priorityQueueImpl) Swap(i, j int) {
	//交换方法
	pqi[i], pqi[j] = pqi[j], pqi[i]
}

// Push 用来将一个对象压入队列中
func (pqi *priorityQueueImpl) Push(x interface{}) {
	item := x.(QItem)
	*pqi = append(*pqi, item)
}

// Pop 将一个对象弹出队列
func (pqi *priorityQueueImpl) Pop() interface{} {

	old := *pqi
	n := len(old)
	item := old[n-1]
	*pqi = old[0 : n-1]
	return item
}

/*
	PriorityQueue 实现优先队列
	PriorityQueue继承了上面的priorityQueueImpl实现的方法
*/
type PriorityQueue struct {
	priorityQueueImpl
}

// NewPriorityQueue 用来构建PriorityQueue
func NewPriorityQueue() *PriorityQueue {
	var pq PriorityQueue
	//pq是我们定义的PriorityQueue的变量,它内部是一个实现了head方法的[]QItem
	//然后我们使用heap的init方法初始化这个[]QItem,并返回
	heap.Init(&pq.priorityQueueImpl)
	return &pq
}

//下面是给这个PriorityQueue实现一些方法
// Push 用来将一个对象压入到队列中,函数接受实现了接口的对象
func (pq *PriorityQueue) Push(item QItem) {
	heap.Push(&pq.priorityQueueImpl, item)
}
// Pop 用来从队列中弹出一个对象
func (pq *PriorityQueue) Pop() QItem {
	return heap.Pop(&pq.priorityQueueImpl).(QItem)
}
// Front 用来获取当前队列中的最小值
func (pq *PriorityQueue) Front() QItem {
	// 队列中第一位应该就是最小值
	return pq.priorityQueueImpl[0]
}
// Length 用来获取当前队列的长度
func (pq *PriorityQueue) Length() int {
	return pq.priorityQueueImpl.Len()
}
//如果希望一个结构可以存储到PriorityQueue中,需要实现QItem接口中的函数,即Less函数。



type Int int

//这里是示例使用,自定义int来实现less方法,也就是实现了QItem接口
//Int实现了less也就可以创建Int实例对象,然后就可以用NewPriorityQueue来处理这个类型的实例
func (i Int) Less(j QItem) bool {
	return i < j.(Int)
}

func main()  {
	var a [100001]int
	var str string
	pq := NewPriorityQueue()
	n,t:=0,0
	j:=1
	for  {
		c,_ :=fmt.Scan(&n)
		if c==0{
			break
		}else{
			for i:=1;i<=n;i++{
				fmt.Scan(&str)
				le :=pq.Len()
				if str=="New"{
					if le==0{//如果队列为空
						a[j]=1
						fmt.Println(j)
						j++
					}else{//将队列中的首位取出
						it :=pq.Pop()
						/*因为我们做实例使用的是Int,而取出的是一个QItem对象,
						数据队列使用的是int,所以要进行一下处理,先将之转换为字符串,
						然后将字符串转换为int,因为下标都是整数,这样做并不会出现什么问题*/
						str1 :=fmt.Sprintf("%d",it)
						intl, err := strconv.Atoi(str1)
						if err != nil {
							fmt.Println("有问题")
						}
						a[intl]=1
						fmt.Println(intl)
					}
				}else{
					fmt.Scan(&t)
					if t<=len(a)&&a[t]==1{
						a[t]=0
						//我们存入的需要是实现了QItem的对象
						pq.Push(Int(t))
						fmt.Println("Successful")
					}else {
						fmt.Println("Failed")
					}

				}
			}
			break
		}
	}
}

众所周知,牛客算法对于空间复杂度采用了和sc玩家碰见对手非理性操作时的常用招式----“不管!”
因此我并没有考虑其他,甭管什么样子,什么优化,在时间内先做对再讲!
终于在这里插入图片描述
在一身悦耳的特效声音后
我成功的通过了
虽然对比C++多用了很多空间在这里插入图片描述
在这里插入图片描述
然鹅
这个时候
已经错过了干饭人的最佳干饭时间
在这里插入图片描述
而在我兴致勃勃想要去和妹子讲解时,却发现她早早的就放弃了这道题
还来了句
好麻烦啊
麻烦啊
烦啊

啊!!!血是内伤,标题破案了兄弟们!

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昰阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值