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经典题解析.pdf

  • 2017年11月01日 16:47
  • 864KB
  • 下载

Leetcode代码以及解答(1)

  • 2017年10月27日 11:47
  • 130KB
  • 下载

【LeetCode002-003算法/编程练习C++】---Add Two Numbers||寻找最长无重复字母子串。//第三题之后有空要再想一想…

leetcode第2和第3题
  • zmdsjtu
  • zmdsjtu
  • 2016年12月22日 14:19
  • 417

Leetcode题目分类和解法总结Xmind

  • 2017年10月27日 12:11
  • 867KB
  • 下载

LeetCode算法设计

  • 2017年07月26日 18:35
  • 1.52MB
  • 下载

【LeetCode-面试算法经典-Java实现】【所有题目目录索引】

LeetCode算法题典   LeetCode是一个准备面试非常有用的网站,是非常值得去的地方,里面都是一些经典的面试题,这些题目在Google,Microsoft,Facebook,Yahoo等...

leetcode problem 4

  • 2017年08月23日 10:34
  • 5KB
  • 下载

LeetCode 完成题目管理工具

  • 2017年06月10日 21:00
  • 8.15MB
  • 下载

leetcode难度及面试频率

转载自:LeetCode Question Difficulty Distribution               1 Two Sum 2 5 array...

Leetcode Solutions

  • 2017年08月18日 22:06
  • 1.81MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:leetcode
举报原因:
原因补充:

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