leetcode

原创 2016年08月31日 10:30:19

1.创建一种数据结构,使得如下操作时间复杂度为O1):

boolean insert(int val) 如果插入结果已存在,则返回false,反之为true

boolean remove(int val) 要删除的元素存在,则返回true,反之为false

int getRandom() 返回集合中任意元素。概率为该元素出现的次数/元素数总和。

分析:插入要在O(1)之内,很容易。getRandom想要在O(1)时间内,按照元素出现的频率来作为概率,则必须是将所有元素放置(重复元素重复放置)在一维数组中,才能做到。因此,解决删除问题,才是要点。

考虑如下矩阵:

[10,10,20,20,30,30]

当删除10时,删除了a[1]位置的10,然后将元素末尾a[5]30,填充到a[1]

填充后的矩阵

[10,30,20,20,30]

这样,就可以满足getRandom的需求,也能在O(1)时间内完成。

观察如上操作,发现,需要记录每一个元素的下标,每当删除元素时,将集合末尾的元素,直接移动到删除元素的下标处。考虑到重复元素,下标应该是一个集合,而且,这个集合要不断的根据下标值删除,(上例中,就要删除30的下标集合中为5的下标)。为了使这一步时间复杂度为O(1),则只能使用hash

public class RandomizedCollection {
	private Map<Integer, Set<Integer>> map;
	private ArrayList<Integer> arrayList;

	/** Initialize your data structure here. */
	public RandomizedCollection() {
		map = new HashMap<>();
		arrayList = new ArrayList<>();
	}

	/**
	 * Inserts a value to the collection. Returns true if the collection did not
	 * already contain the specified element.
	 */
	public boolean insert(int val) {
		boolean mark = false;
		if (!map.containsKey(val)) {
			Set<Integer> set = new HashSet<>();
			map.put(val, set);
			mark = true;
		}
		map.get(val).add(arrayList.size());
		arrayList.add(val);
		return mark;
	}

	/**
	 * Removes a value from the collection. Returns true if the collection
	 * contained the specified element.
	 */
	public boolean remove(int val) {
		HashSet<Integer> set = new HashSet<>();
		set.remove(0);
		if (!map.containsKey(val)) {
			return false;
		}

		int indexOfVal = map.get(val).iterator().next();
		map.get(val).remove(indexOfVal);
		if (map.get(val).size() == 0)
			map.remove(val);
		// 如果删除的不是尾部元素
		if (indexOfVal != arrayList.size() - 1) {
			int indexLast = arrayList.size() - 1;
			int elemLast = arrayList.get(indexLast);// 获取最后一个元素

			arrayList.set(indexOfVal, elemLast);// 将该元素填补到被删除元素的空白处。
			map.get(elemLast).remove(indexLast);
			map.get(elemLast).add(indexOfVal);
		}
		arrayList.remove(arrayList.size() - 1);
		return true;
	}

	/** Get a random element from the collection. */
	public int getRandom() {
		return arrayList.get(new Random().nextInt(arrayList.size()));
	}
}


2.小矩形组成大矩形

Given N axis-aligned rectangles where N > 0, determine if they all together form an exact cover of a rectangular region.

Each rectangle is represented as a bottom-left point and a top-right point. For example, a unit square is represented as [1,1,2,2]. (coordinate of bottom-left point is (1, 1) and top-right point is (2, 2)).

分析:最后的大矩形,其最左下角的坐标是矩形集合中的最左下坐标,其右上亦如此。只要获取到这两个坐标,矩阵就唯一确定。大矩形的面积,必然等于所有小矩形的面积。

有一种特殊情况:重合的面积正好补齐了残缺的面积。仔细观察大矩形可知,除去四个顶点处的点外,其他小矩形的点都有偶数个。将每个小矩形的四个点放入set集合中,每当遇到重复的则删除,最后剩下的必然是四个顶点处的点。

	public boolean isRectangleCover(int[][] rectangles) {
		if (null == rectangles || 0 > rectangles.length || 4 != rectangles[0].length) {
			return false;
		}
		int xLeft = Integer.MAX_VALUE;
		int yLeft = Integer.MAX_VALUE;

		int xRight = Integer.MIN_VALUE;
		int yRight = Integer.MIN_VALUE;

		int areaSum = 0;
		Set<String> set = new HashSet<>();
		for (int i = 0; i < rectangles.length; i++) {
			xLeft = Math.min(xLeft, rectangles[i][0]);
			yLeft = Math.min(yLeft, rectangles[i][1]);

			xRight = Math.max(xRight, rectangles[i][2]);
			yRight = Math.max(yRight, rectangles[i][3]);

			areaSum += (rectangles[i][2] - rectangles[i][0]) * (rectangles[i][3] - rectangles[i][1]);

			// 将四个点添加到set集合中
			addPoint(rectangles[i][0] + "" + rectangles[i][1], set);
			addPoint(rectangles[i][0] + "" + rectangles[i][3], set);
			addPoint(rectangles[i][2] + "" + rectangles[i][1], set);
			addPoint(rectangles[i][2] + "" + rectangles[i][3], set);
		}

		int newArea = (xRight - xLeft) * (yRight - yLeft);
		if (newArea != areaSum) {
			return false;
		} else {
			if (set.size() == 4 && set.contains(xLeft + "" + yLeft) && set.contains(xLeft + "" + yRight)
					&& set.contains(xRight + "" + yLeft) && set.contains(xRight + "" + yRight)) {
				return true;
			} else {
				return false;
			}
		}
	}

	private void addPoint(String key, Set<String> set) {
		if (set.contains(key)) {
			set.remove(key);
		} else {
			set.add(key);
		}
	}




leetcode抽风还是被墙

隔了段时间没刷leet等再上的时候,先是发现leet改版了,新题目要高级会员才能刷,当然那是要缴会费的。不过没事还有一百多道老题目可以刷。然后刷题的时候,时不时发生提交失败的情况,现在,连leet首页...
  • kakulukia
  • kakulukia
  • 2015年08月11日 19:44
  • 1032

本博客LeetCode题解索引及各类算法问题小结汇总(C++实现)

Some explains: 1),The current problems have been solved:Welcome, EbowTang! You have solved 101 / 316...
  • EbowTang
  • EbowTang
  • 2016年02月15日 17:18
  • 5689

LeetCode最常见的面试笔试题总结

找了一段时间的实习,总结一下LeetCode上面试出现频率比较高的题,只总结一部分,后续还会继续更新。一、Two Sum题意是给出一个数组,输出和为k的两个数。数组为无序的。 这道题的解题思路是先把...
  • u014486880
  • u014486880
  • 2016年04月26日 23:55
  • 8607

LeetCode总结 -- 图篇

图的算法跟树一样是准备面试中必不可少的一块,不过图的方法很容易概括,面试中考核的无非就是两种搜索算法:深度优先搜索和广度优先搜索。LeetCode中关于图的问题有以下几个:Clone GraphWor...
  • linhuanmars
  • linhuanmars
  • 2014年09月18日 06:55
  • 12654

LeetCode 问题汇总(算法,难度,频率)

Id Question Difficulty Frequency Data Structures Algorithms 1 T...
  • sbitswc
  • sbitswc
  • 2014年03月13日 11:58
  • 12196

[leetcode]--刷leetcode算法目录和算法总结目录

这篇博文是记录所有刷leetcode算法的目录以及全部源码的github地址:所有代码的github地址:https://github.com/leetcode-hust/leetcode/tree/...
  • u010853261
  • u010853261
  • 2017年02月02日 07:54
  • 1098

leetcode总结-- 排序算法(内部排序)

包括quick_sort(不稳定), merge_sort(稳定), bubble_sort(稳定), selection_sort(不稳定), insertion_sort(稳定)code整理如下,...
  • xyqzki
  • xyqzki
  • 2016年01月18日 15:36
  • 760

leetcode面试频率

leetcode题目面试频率总结
  • Alpaca12
  • Alpaca12
  • 2016年06月12日 16:33
  • 1449

leetcode | 二叉树的前序遍历、中序遍历、后续遍历的非递归实现

Binary Tree Preorder Traversal:https://leetcode.com/problems/binary-tree-preorder-traversal/ Binary...
  • quzhongxin
  • quzhongxin
  • 2015年06月01日 19:20
  • 1411

LeetCode总结--二分查找篇

二分查找算法虽然简单,但面试中也比较常见,经常用来在有序的数列查找某个特定的位置。在LeetCode用到此算法的主要题目有: Search Insert Position Search for a...
  • linhuanmars
  • linhuanmars
  • 2014年06月16日 10:50
  • 13691
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:leetcode
举报原因:
原因补充:

(最多只允许输入30个字)