659. 分割数组为连续子序列

  1. 分割数组为连续子序列
    给你一个按升序排序的整数数组 num(可能包含重复数字),请你将它们分割成一个或多个子序列,其中每个子序列都由连续整数组成且长度至少为 3 。

1.哈希表+最小堆

	public boolean isPossible(int[] nums) {
		Map<Integer,PriorityQueue<Integer>>map=new HashMap<Integer,PriorityQueue<Integer>>();
		//哈希表的键是子序列的最后一个数字,值是最小堆(存储的子序列长度)
		for(int x :nums) {
			if(!map.containsKey(x)) {//初始创建
				map.put(x, new PriorityQueue<Integer>());
			}
			if(map.containsKey(x-1)) {
				int preLen=map.get(x-1).poll();//get最小堆再堆顶出队
				if(map.get(x-1).isEmpty()) {//如果堆空了
					map.remove(x-1);//删除哈希表上的这个节点
				}
				map.get(x).offer(preLen+1);
				//将子序列长度加1之后作为以x结尾的子序列长度
			}
			else {//如果哈希表中不存在以x-1 结尾的子序列
				map.get(x).offer(1);
				//则新建一个长度为1 的以x结尾的子序列				
			}
		}
		//遍历每个最小堆的堆顶元素判断是否个子序列小于3
		Set<Map.Entry<Integer, PriorityQueue<Integer>>> entrySet=map.entrySet();
		//键值对映射关系的集合,可使用它对map进行遍历。
		for(Map.Entry<Integer, PriorityQueue<Integer>> entry:entrySet) {//遍历映射集合中的每个映射元素
			PriorityQueue<Integer>queue=entry.getValue();//取值,即取最小堆
			if(queue.peek()<3)
				return false;
		}
		return true;
    }

tips:
1.堆(队)操作:

stack.poll();//堆顶出队
stack.offer(1);//1入队
stack.peek();//取堆顶元素的值,不删除元素

2.哈希表:

Map<Integer,PriorityQueue<Integer>> map=new HashMap<Integer,PriorityQueue<Integer>>();
//创建
map.put(x, new PriorityQueue<Integer>());//创建节点
map.remove(x-1);//删除节点

3.遍历哈希表

Set<Map.Entry<Integer, PriorityQueue<Integer>>> entrySet=map.entrySet();
//创建哈希表相关的映射
PriorityQueue<Integer>queue=entry.getKey();//取某个映射的键
PriorityQueue<Integer>queue=entry.getValue();//取某个映射的值

2.贪心法:

    public boolean isPossible(int[] nums) {
		Map<Integer,Integer> countMap=new HashMap<Integer,Integer>();
		Map<Integer,Integer> endMap=new HashMap<Integer,Integer>();
		//先计算每个数字出现的次数
		for(int num:nums) {
			countMap.put(num, countMap.getOrDefault(num, 0)+1);
		}
		for(int num:nums) {
			int count=countMap.getOrDefault(num, 0);
			if(count>0) {//还有剩余次数
				int countEnd=endMap.getOrDefault(num-1, 0);
				if(countEnd>0) {//将x插入x-1队列
					countMap.put(num, count-1);
					endMap.put(num-1, countEnd-1);
					endMap.put(num, endMap.getOrDefault(num, 0)+1);
				}
				else {//没有x-1,就要重新创建
					int count1=countMap.getOrDefault(num+1, 0);
					int count2=countMap.getOrDefault(num+2, 0);
					if(count1==0||count2==0)//x+1,x+2没有剩余次数,就失败了
						return false;
					countMap.put(num, count-1);//x的剩余次数少一
					countMap.put(num+1, count1-1);//x+1的剩余次数少一
					countMap.put(num+2, count2-1);//x+2的剩余次数少一
					endMap.put(num+2,endMap.getOrDefault(num+2, 0)+1);//x+2的结尾次数加一
				}
			}
		}
		return true;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值