[LeetCode] 第160场周赛题解

第一题:

因为该函数具有严格的单调性,所以可以二分,即枚举x二分y,但数据范围过小没啥必要。

public class Solution {
	public List<List<Integer>> findSolution(CustomFunction func, int z) {
		List<List<Integer>> ans=new ArrayList<List<Integer>>();
        for(int x=1;x<=1000;x++) {
        	int l=1;
        	int r=1000;
        	int y=-1;
        	while(l<=r) {
        		int mid=(l+r)>>1;
        	    if(func.f(x, mid)>=z) {
        	    	if(func.f(x, mid)==z) {
        	    		y=mid;
        	    		break;
        	    	}
        	    	r=mid-1;
        	    }
        	    else
        	    	l=mid+1;
        	}
        	if(y==-1)
        		continue;
        	ArrayList<Integer> temp=new ArrayList<Integer>();
        	temp.add(x);
        	temp.add(y);
        	ans.add(temp);
        }
        return ans;
    }
}

class CustomFunction {
	public int f(int x, int y) {
		return 0;
	}
}

第二题:

考虑建图,然后找到一个长度为2^n的环。

public class Solution {
	public ArrayList<Integer>[] G;
	public static boolean find=false;
	
	public List<Integer> circularPermutation(int n, int start) {
		G=new ArrayList[1<<n];

		for(int i=0;i<G.length;i++)
			G[i]=new ArrayList<Integer>();
		for(int i=0;i<G.length;i++)
			G[i]=new ArrayList<Integer>();
		for(int i=0;i<(1<<n);i++) {
			for(int j=0;j<n;j++) {
				G[i].add(i^(1<<j));
			}
		}
		List<Integer> ans=new ArrayList<Integer>();
		boolean[] vis=new boolean[1<<n];
		dfs(start,vis,ans,start,n);
		
		return ans;
    }
	
	
	public void dfs(int u,boolean[] vis,List<Integer> ans,int start,int n) {
		ans.add(u);
		vis[u]=true;
		for(int v:G[u]) {
			if(v==start&&ans.size()==(1<<n)) {
				find=true;
				return ;
			}
			if(vis[v])
				continue;
			dfs(v,vis,ans,start,n);
			if(find)
				return ;
		}
		vis[u]=false;
		ans.remove(ans.size()-1);
	}
}

第三题:

二进制枚举暴力,感兴趣的可以考虑下01背包能做吗?我觉得没法枚举状态。

public class Solution {
	public int maxLength(List<String> arr) {
        int n=arr.size();
        int ans=0;
        
        for(int i=0;i<(1<<n);i++) {
        	boolean[] use=new boolean[26];
        	boolean[] jud=new boolean[26];
        	int temp=0;
        	for(int j=0;j<n;j++) {
        		if((i&(1<<j))!=0) {
        			boolean flag=true;
        			Arrays.fill(jud, false);
        			for(char v:arr.get(j).toCharArray()) {
        				if(jud[v-'a']) {
        					flag=false;
        					break;
        				}
        				jud[v-'a']=true;
        				if(use[v-'a']) {
        					flag=false;
        					break;
        				}
        			}
        			if(flag) {
        				temp+=arr.get(j).length();
        				for(char v:arr.get(j).toCharArray())
        					use[v-'a']=true;
        			}
        		}
        	}
        	ans=Math.max(ans, temp);
        }
        return ans;
    }
}

第四题:

dp[i][j]表示长为i宽为j的矩形最少可有多少个正方形拼接而成。

当i=j时答案肯定为1,当i!=j时考虑以下三种切法:

1.纵向切一刀

2.横向切一刀

3.中间留个正方形,然后枚举中间这个正方形的边延伸出去的情况,需要讨论的东西比较多,但应该是正解。

对于上述的第三种切法,我只枚举了中间的块的大小以及摆放的位置,并没有做其他的讨论,虽然过了,但我觉得应该不是正解。

public class Solution {
	public int tilingRectangle(int n, int m) {
        int[][] dp=new int[n+1][m+1];
        for(int[] temp:dp)
        	Arrays.fill(temp, Integer.MAX_VALUE/8);
        for(int i=1;i<=n;i++) {
        	for(int j=1;j<=m;j++) {
        		if(i==j) {
        			dp[i][j]=1;
        			continue;
        		}
        		for(int k=1;k<i;k++)
        			dp[i][j]=Math.min(dp[i][j], dp[k][j]+dp[i-k][j]);
        		for(int k=1;k<j;k++)
        			dp[i][j]=Math.min(dp[i][j], dp[i][k]+dp[i][j-k]);
        		for(int k=1;k<=Math.min(i, j);k++) {
        			for(int x=1;x+k<=i;x++) {
        				for(int y=1;y+k<=j;y++) {
        					dp[i][j]=Math.min(dp[i][j], dp[x][y+k]+dp[x+k][j-y-k]+dp[i-x][y]+dp[i-x-k][j-y]+1);
        				}
        			}
        		}
        	}
        }
        return dp[n][m];
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值