Wish onsite 面经整理

这里帖一下目前找到的仅有几道非Leetcode的题,附上自己的解答

欢迎补充更多面经或者其他解法


红绿灯:
[红, 绿, 绿, 红, 红]. 翻转⼀个⼦区间(红变绿,绿变红),使得绿灯个数最⼤. 返回区间的起点和终点

解答

这里假设返回区间的左右端都是inclusive的, 比如返回[2,2]就代表区间包含一个元素,下标为2
本质上是实现 Kadanes’ algorithm, O(n) time, O(1) space
代码

import java.util.*;

class TrafficLight{
	public static int[] interval (String[] colors) {
		int[] res = new int[2];
		int[] encode = new int[colors.length];
		for (int i = 0; i < colors.length; i++) {
			if (colors[i].equals("R")) encode[i] = 1;
			else encode[i] = -1;
		}
		int max_so_far = 0;
		int max_ending_here = 0;
		int start = 0, end = 0, next_start = 0;
		for (int i = 0; i < colors.length; i++) {
			max_ending_here += encode[i];
			//System.out.println(i);
			//System.out.println(max_ending_here);
			if (max_ending_here < 0) {
				//System.out.println("start next");
				if (i < colors.length - 1) next_start = i + 1;
				max_ending_here = 0;
			} else if (max_so_far < max_ending_here) {
				//System.out.println("end here");
				end = i;
				if (next_start > 0) start = next_start;
				max_so_far = max_ending_here;
			}
		}
		res[0] = start; 

		res[1] = end;
		return res;
	}

	public static void main(String[] args) {
		String[] colors = new String[]{"R", "G", "G", "R", "R"};
		int[] res = interval(colors);
		for (int r : res) {
			System.out.println(r);
		}	

		String[] colors1 = new String[]{"G", "R", "G", "G", "R", "R"};
		int[] res1 = interval(colors1);
		for (int r : res1) {
			System.out.println(r);
		}
	}
}

设计一个买/卖一个商品的class,提供两个功能,buy(price, quantity)和sell(price, quantity),意思就是有人出多少钱买多少个这个商
品,或者有人标价多少钱卖这个商品,返回值是买到或者卖出的数量,例子:
sell(10, 20) 返回0,暂时没人买,把这个数据存着
buy(5, 20) 返回0,没有人用<=5的价格卖这个商品,把这个订单也存起来
sell(4, 25) 返回20,上一行那个买家就买到了20个,然后剩5个存起来
buy(12, 30) 返回25,第一行的20个被买了,还有上一行剩的5个也被买了,然后还差5个的订单,存起来
另外,如果有多个卖家用不同的价格卖同一个商品,并且价格都低于当前buy的价格,先买哪个无所谓。反之亦然

概要

用两个treemap 分别存买方(buyMap)和卖方(sellMap)目前剩余的订单,key是价格,value是存货量。
每次buy交易,在sellMap中搜索出价不高于本次买方出价的存货,从价格低的搜起,如果某一价位的商品被买完,及时清空对应的map entry。 最后如果本次购买的量还有剩余(价格不高于出价的商品都买完了),剩余的加入对应的buyMap.

对于sell交易,只需要改为从buyMap中搜索价格不低于本次出价的存货,最后更新对应的sellMap就可以

复杂度:假设有n条交易记录, 用来存放map的空间是O(n), 每次交易都需要遍历一遍当前map, 时间上是O(n^2) 的


class BuyerSeller{
	private Map<Integer, Integer> sellMap; 
	private Map<Integer, Integer> buyMap;
	private int sellStock;
	private int buyStock;

	public BuyerSeller() {
		this.buyMap = new TreeMap<>();
		this.sellMap = new TreeMap<>();
		sellStock = 0;
		buyStock = 0;
	}

	public int sell(int price, int quantity) {
		int res = quantity; // residual quantity not sold

		if (buyMap.containsKey(price)) {
			int bq = buyMap.get(price);
			if (bq > quantity) {
				buyMap.put(price, bq - quantity);
				return quantity;
			} else {
				res = res - bq;
				buyMap.remove(price);			
			}
		} 

		List<Integer> keys = new ArrayList<>(); //store price entry to be removed
		List<Integer> values = new ArrayList<>(); //store coresponding values

		for (int p: buyMap.keySet()) {
			if (p < price) {
				// do nothing
			} else {
				int q = buyMap.get(p);
				if (q > res) {
					keys.add(p);
					values.add(q - res);
					res = 0;
					break;
				} else {
					res = res - q;
					keys.add(p);
					values.add(0);
				}
			}
		}

		for (int i = 0; i < keys.size(); i++) {
			if (values.get(i) > 0) buyMap.put(keys.get(i), values.get(i));
			else buyMap.remove(keys.get(i));
		}
				
		if (res > 0) {
			if (sellMap.containsKey(price)) {
				int cur_q = sellMap.get(price);
				sellMap.put(price, res + cur_q);
			} else {
				sellMap.put(price, res);
			}
		}
		return quantity - res;
	}

	public int buy(int price, int quantity) {
		int res = quantity; //residual quantity not bought

		if (sellMap.containsKey(price)) {
			int sq = sellMap.get(price);
			if (sq > quantity) {
				sellMap.put(price, sq - quantity);
				return quantity;
			} else {
				res = res - sq;
				sellMap.remove(price);	
			}
		} 

		List<Integer> keys = new ArrayList<>(); //store price entry to be removed
		List<Integer> values = new ArrayList<>(); //store coresponding values

		for (int p: sellMap.keySet()) {
			if (p <= price) {
				int q = sellMap.get(p);
				if (q > res) {
					keys.add(p);
					values.add(q - res);
					res = 0;
					break;
				} else {
					res = res - q;
					keys.add(p);
					values.add(0);
				}
			} else {
				break;
			}
		}

		for (int i = 0; i < keys.size(); i++) {
			if (values.get(i) > 0) sellMap.put(keys.get(i), values.get(i));
			else sellMap.remove(keys.get(i));
		}

		if (res > 0) {
			if (buyMap.containsKey(price)) {
				int cur_q = buyMap.get(price);
				buyMap.put(price, res + cur_q);
			} else {
				buyMap.put(price, res);
			}
				
		}	
		return quantity - res;
	}

	// get number of products not bought
	public int stockBuySize() {
		for (int k : buyMap.keySet()) {
			buyStock += buyMap.get(k);
		}
		return buyStock;
	}

	// get number of products not sold
	public int stockSellSize() {
		for (int k : sellMap.keySet()) {
			sellStock += sellMap.get(k);
		}
		return sellStock;
	}
}

class Trade {
	public static void main(String[] args) {
		System.out.println("trade 1");
		BuyerSeller bs = new BuyerSeller();
		System.out.println("sell amount: " + bs.sell(10, 20));
		System.out.println("buy amount: " + bs.buy(5, 20));
		System.out.println("sell amount: " + bs.sell(4, 25));
		System.out.println("buy amount: " + bs.buy(12, 30));
		System.out.println("number of products needed to buy: " + bs.stockBuySize());
		System.out.println("number of products needed to sell: " + bs.stockSellSize());

		System.out.println("trade 2");
		BuyerSeller bs1 = new BuyerSeller();
		System.out.println("sell amount: " + bs1.sell(1, 20));
		System.out.println("buy amount: " + bs1.buy(2, 15));
		System.out.println("sell amount: " + bs1.sell(1, 25));
		System.out.println("buy amount: " + bs1.buy(2, 30));
		System.out.println("number of products needed to buy: " + bs1.stockBuySize());
		System.out.println("number of products needed to sell: " + bs1.stockSellSize());
	}
}

Maximal sum increasing subsequence

Given an array of n positive integers. Write a program to find the sum of maximum sum subsequence of the given array such that the integers in the subsequence are sorted in increasing order. For example, if input is {1, 101, 2, 3, 100, 4, 5}, then output should be 106 (1 + 2 + 3 + 100), if the input array is {3, 4, 5, 10}, then output should be 22 (3 + 4 + 5 + 10) and if the input array is {10, 5, 4, 3}, then output should be 10。 链接

解答

思路还是dp, 存结束于每个下标位置的最大increasing subsequence sum
时间复杂度O(n^2), 空间复杂度O(n)
代码

import java.util.*;
class maxSumIS {
	public static int maxSumIS(int[] arr) {
		if (arr == null || arr.length == 0) return 0;
		int len = arr.length;
		if (len == 1) return arr[0]; //lenght = 1 base case
		int[] max_arr = new int[len];
		max_arr[0] = arr[0];
		int res = max_arr[0];
		for (int i = 1; i < len; i++) {
			int max = 0;
			for (int j = 0; j < i; j++) {
				if (arr[j] < arr[i] && max_arr[j] > max) {
					max = max_arr[j];
				}
			}
			max_arr[i] = max + arr[i];	// if no element smaller than it, then should be length === 1
			if (max_arr[i] > res) res = max_arr[i];
		}
		return res;
	}	

	public static void main(String[] args) {
		int[] arr = new int[]{1, 101, 2, 3, 100, 4, 5};
		System.out.println(maxSumIS(arr));

		int[] arr1 = new int[]{10, 5, 4, 3};
		System.out.println(maxSumIS(arr1));
	}
}
1 Like

Maximal sum increasing subsequence

这题可以用treemap g4g的解法时间复杂度高了

能具体问下怎么做的么,key 和 value分别是什么?

key就是array里面的element value是count

可以说说treemap的解法吗?