啥时候能稳定啊,一遇到内推场就是神仙打架。第 188 场力扣周赛题解_三元组

5404. 用栈操作构建数组

思路:判断target[i]是否等于当前list的首元素即可,不是的话,就执行先加入后弹出操作,否则只执行push操作。

class Solution {
    public List<String> buildArray(int[] target, int n) {
    	
    	int num=1;
    	List<String> list=new ArrayList<>();
    	
    	for(int i=0;i<target.length;i++) {
    		while(target[i]>num) {
    			num++;
    			list.add("Push");
    			list.add("Pop");
    		}
    		num++;
    		list.add("Push");
    	}
    	
    	return list;
    }
}

5405. 形成两个异或相等数组的三元组数目

思路:考察异或的简单性质:a^b=c等价于a^c=b,依靠这一性质我们可以预处理出来前缀异或和从而方便求出任意区间的异或和,之后暴力i,j,k的值即可。

class Solution {
    public int countTriplets(int[] arr) {
    	
    	int ans=0;
    	int n=arr.length;
    	int[] sum=new int[n];
    	
    	sum[0]=arr[0];
    	for(int i=1;i<n;i++)
    		sum[i]=sum[i-1]^arr[i];
    	
    	for(int i=0;i<n;i++)
    		for(int j=i+1;j<n;j++)
    			for(int k=j;k<n;k++) {
    				int val1=0,val2=0;
    				if(i==0) val1=sum[j-1];
    				else val1=sum[j-1]^sum[i-1];
    				val2=sum[k]^sum[j-1];
    				if(val1==val2) ans++;
    			}
    	
    	return ans;
    }
}

5406. 收集树上所有苹果的最少时间

思路:对于树上的每个节点,我们走到它的唯一可能是该节点或者该节点为根的子树中有苹果。若子树中有苹果,并且不止一个,则最优的方法一定是先把这个子树里的苹果摘完再回去。若该子树已经摘完了,为了不影响答案,我们将这个子树缩为一个点后往上遍历就ok了,这是我的做法。

class Solution {
	
	int n;
	int ans;
	boolean[] mark;
	List<List<Integer>> list;
	
    public int minTime(int n, int[][] edges, List<Boolean> hasApple) {
        
    	ans=0;
    	this.n=n;
    	mark=new boolean[n];
    	list=new ArrayList<>();
    	
    	for(int i=0;i<n;i++) {
    		list.add(new ArrayList<>());
    		mark[i]=hasApple.get(i);
    	}
    	
    	for(int i=0;i<edges.length;i++){
    		list.get(edges[i][0]).add(edges[i][1]);
    		list.get(edges[i][1]).add(edges[i][0]);
    	}
    	
    	dfs(0,-1);
    	if(ans==1 && mark[0]) return 0;
    	return ans;
    }
    
    private int dfs(int u,int p) {
    	
    	int res=0;
    	for(int i=0;i<list.get(u).size();i++) {
    		int v=list.get(u).get(i);
    		if(v==p) continue;
    		res+=dfs(v,u);
    	}
    	
    	if(res>0) {
    		ans+=res*2;
    		return 1;
    	}
    	if(mark[u]) return 1;
    	return 0;
    }
}

5407. 切披萨的方案数

思路:我们定义dp[i][j][k]:表示剩下的大小为i*j的披萨块并且还剩下k次没切的方案数。之后可以采用记忆化搜索暴力。

class Solution {
	
	long[][][] dp;
	private int mod=1000000007;
	
    public int ways(String[] pizza, int k) {
    	
    	int sum=0;
    	int m=pizza.length;
    	int n=pizza[0].length();
    	dp=new long[m+1][n+1][k];
    	for(int i=0;i<m;i++) {
    		for(int j=0;j<n;j++)
    			if(pizza[i].charAt(j)=='A')
    				sum++;
    	}
    	
    	for(int i=0;i<=m;i++)
    		for(int j=0;j<=n;j++)
    			for(int h=0;h<k;h++)
    				dp[i][j][h]=-1;
    	
    	if(sum<k) return 0;
    	
    	return (int)(dfs(pizza,0,0,m,n,k-1)%mod);
    	
    }
    
    private long dfs(String[] s,int x,int y,int m,int n,int k) {
    	
    	if(k==0) {
    		dp[m-x][n-y][k]=0;
    		for(int i=x;i<m;i++)
    			for(int j=y;j<n;j++) {
    				if(s[i].charAt(j)=='A') {
    					dp[m-x][n-y][k]=1;
    					break;
    				}
    			}
    		
    		return dp[m-x][n-y][k];
    	}
    	
    	long res=0;
    	
    	if(dp[m-x][n-y][k]!=-1)
    		return dp[m-x][n-y][k];
    	
		for(int i=x;i<m;i++) {
			if(check(s,x,y,i,n-1) && i+1<m)
				res=(res+dfs(s,i+1,y,m,n,k-1))%mod;
		}
		for(int j=y;j<n;j++) {
			if(check(s,x,y,m-1,j) && j+1<n)
				res=(res+dfs(s,x,j+1,m,n,k-1))%mod;
		}
    	
    	return dp[m-x][n-y][k]=res;
    }
    
    private boolean check(String[] s,int x,int y,int m,int n) {
    	for(int i=x;i<=m;i++)
    		for(int j=y;j<=n;j++)
    			if(s[i].charAt(j)=='A')
    				return true;
    	return false;
    }
}