Leetcode双周赛22总结

这次周赛排名:1800/5632
破天荒做出了两题,第三题卡在memory exceed error。继续加油!

  1. Find the distance value between two arrays
    Given two integer arrays arr1 and arr2, and the integer d, return the distance value between the two arrays.
    The distance value is defined as the number of elements arr1[i] such that there is not any element arr2[j] where |arr1[i]-arr2[j]| <= d.

也就是说要对arr1 arr2做一个笛卡尔积,如果第一个的每一个元素都大于第二个的每一个元素,那么算作一个distance。

public int findTheDistanceValue(int[] arr1, int[] arr2, int d) {
        int res = 0;
		for (int a : arr1) {
			int temp = 1;
			for (int b : arr2) {
				if (Math.abs(a - b) <= d)
					temp = 0;
			}
			res += temp;
		}
		return res;
    }

上面是我的做法: 一开始把temp设为1,然后如果有一次<=d的情况,就把temp设为0。这个操作逻辑上是什么呢?就是AND操作。只要有一个元素为零,则结果为0.

public int findTheDistanceValue2(int[] arr1, int[] arr2, int d) {
		int res = arr1.length;
		outer: 
		for (int a : arr1) {
			for (int b : arr2) {
				if (Math.abs(a - b) <= d) {
					res--;
					continue outer;
				}
			}
		}
		return res;
	}

这是参考第三名的日本选手uwi的答案。他首先把res设为所有都为1,然后如果碰到违反的情况,则减一。注意这里的continue是外围的forloop,因此需要用便签outer来标识。



  1. Sort Integers by The Power Value
    The power of an integer x is defined as the number of steps needed to transform x into 1 using the following steps:
    if x is even then x=x/2
    if x is odd then x=3*x+1

按照power定义排序数组,这题比较简单。

public int getKth(int lo, int hi, int k) {

		List<Integer> li = new ArrayList<>();
		while (lo <= hi) {
			li.add(lo);
			lo += 1;
		}

		Collections.sort(li, new Comparator<Integer>() {
			@Override
			public int compare(Integer a, Integer b) {
				int pa = getPower(a);
				int pb = getPower(b);
				return pa == pb ? a - b : pa - pb;
			}
		});
		return li.get(k - 1);
	}

	private int getPower(int a) {
		int power = 0;
		while (a != 1) {
			if (a % 2 == 0) {
				a /= 2;
			} else {
				a = a * 3 + 1;
			}
			power += 1;
		}
		return power;
	}

上面是我的做法。
需要牢记list的排序是用Collections.sort()



  1. Cinema Seat Allocation
    A cinema has n rows of seats, numbered from 1 to n and there are ten seats in each row, labelled from 1 to 10 as shown in the figure above.
    Given the array reservedSeats containing the numbers of seats already reserved, for example, reservedSeats[i]=[3,8] means the seat located in row 3 and labelled with 8 is already reserved.
    Return the maximum number of four-person families you can allocate on the cinema seats.
    电影院的每排有10个座位,排序是1 2 3 || 4 5 6 7 || 8 9 10,中间是走廊。
    问最多能容纳多少四口人,要求是4个人必须连着坐,2+2的被走廊隔开也算相连。

这题比较难。一开始想的是先把被预定的座位复制到二位数组,然后一行行检查是否可以容下四个人。但是内存不够。
这是一个比较典型的位操作问题。

public int maxNumberOfFamilies(int n, int[][] reservedSeats) {
		// sort reserved seats
		Arrays.sort(reservedSeats, new Comparator<int[]>() {
			public int compare(int[] a, int[] b) {
				if (a[0] != b[0])
					return a[0] - b[0];
				else 
					return a[1] - b[1];
			}
		});

		int res = 2 * n; // max families in total
		int i = 0;
		while (i < reservedSeats.length) {
			int j = i;

			// find reserved seats in a row
			while (j < reservedSeats.length && reservedSeats[j][0] == reservedSeats[i][0]) {
				j++;
			}
			res -= 2;
			int pattern = 0;

			// k is the starting position of reserved seat in a row
			// note that there is one more bit more, 0
			// 10 9 8 7 6 5 4 3 2 1 | 0
			for (int k = i; k < j; k++) {
				pattern |= 1 << reservedSeats[k][1]; // OR operation, retains 1
			}

			// mask for seat 9 to 2
			if ((pattern & ((1 << 10) - (1 << 2))) == 0)
				res += 2;
			// mask for 7 6 5 4
			else if ((pattern & ((1 << 8) - (1 << 4))) == 0)
				res++;
			// mask for 5 4 3 2
			else if ((pattern & ((1 << 6) - (1 << 2))) == 0)
				res++;
			// mask for 9 8 7 6
			else if ((pattern & ((1 << 10) - (1 << 6))) == 0)
				res++;

			i = j; // update next row reserved position
		}
		return res;
	}

上面是学uwi的解法。

  • 首先,把预定座位数组排序,排序的顺序是行数然后列数。
  • 然后,我们观察到每一行最多能容纳两组四人。初始化res为最大的容量。
  • 然后forloop逐个看每个预定的座位,j代表的是本行中最大的预定的位置。
  • 对预定位置的列位置进行位操作,得到pattern。注意,pattern是有11位的,因此最右边的0是没用的。
  • 然后对pattern进行mask,mask是1,AND操作 把无关的位数抹掉。如果最后是0,那么说明没有座位被预定。

需要注意的是:用到了减法求得mask的方法。比如第一个:1<<10 - 1<<2 得到的是9到2的mask。
最后,我们需要检查下一行,需要把当前位置j赋给i。



PS:

  • 无意看到了周赛排行榜第四名,也是排名第一的中国选手Hu Zecong的博客。 果然周赛排在前面的都是acmer。
  • 永远记得人外有人。不要目光狭隘,不要止步不前。 仰望星空,脚踏实地。

你可能感兴趣的:(leetcode周赛)