方法一:枚举子集
数据范围有限,直接枚举子集计算异或和。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public int subsetXORSum(int[] nums) { int len = nums.length; int res = 0; for(int i=0;i<(1<<len);i++){ res += getXOR(nums,i); } return res; } public int getXOR(int[] nums,int i){ int sum = 0; if(i==0) return 0; for(int k=0;k<31;k++){ if((i&k)!=0) sum^= nums[k]; } return sum; }
|
方法一:模拟
可以交换:abs(OneN-ZeroN)<=1 否则返回-1
交换次数:字符串只有0,1,最少交换次数一定是最终字符串和当前字符串差异/2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public int minSwaps(String s) { int OneN = count(s,'1'),ZeorN = count(s,'0'); if(Math.abs(OneN-ZeorN)>1) return -1; int cnt1 = 0,cnt2 = 0; char c; for(int i=0;i<s.length();i++){ if(i%2==0) c = '1'; else c = '0'; if(s.charAt(i)!=c) cnt1++; } for(int i=0;i<s.length();i++){ if(i%2==0) c = '0'; else c = '1'; if(s.charAt(i)!=c) cnt2++; } if(OneN==ZeorN) return Math.min(cnt1,cnt2)/2; if(OneN >ZeorN) return cnt1/2; return cnt2/2; } public int count(String s,char c){ int res = 0; for(char ch : s.toCharArray()){ if(ch==c) res++; } return res; }
|
方法一: hash
设计题,寻找两数之和可以用Map优化查询时间,本题依然可以采用Map优化,关于Add修改数组,只需要修改map即可;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class FindSumPairs { int[] nums1; int[] nums2; Map<Integer,Integer> map; public FindSumPairs(int[] nums1, int[] nums2) { this.nums1 = nums1; this.nums2 = nums2; this.map = new HashMap<>(); for(int i: nums2){ map.put(i, map.getOrDefault(i,0)+1); } }
public void add(int index, int val) { int newVal = nums2[index]+val; map.put(newVal, map.getOrDefault(newVal,0)+1); map.put(nums2[index], map.getOrDefault(nums2[index],0)-1); }
public int count(int tot) { int res = 0; for(int i:nums1){ if(map.containsKey(tot-i)){ res += map.get(tot-i); } } return res; } }
|
方法一:DP
看大佬题解,应该是常见板子题。思路是:由于数组1-n,选择恰好可以看到k个,就是将n个数分成m个集合,有几种分配方式。
定义:dp[i][j] 为i个数分为j个集合的方案数,dp[i][j] = dp[i-1][j-1] + (i-1)dp[i-1][j], 即:若i-1个数分成了m-1个集合,那么第i个数自己独立成集合,如果i-1个数分配成了m个集合,第i个数任意插入i-1的集合中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Solution { int MOD = 1000000000+7; public int rearrangeSticks(int n, int k) { long[][] dp = new long[n+1][n+1]; dp[0][0] = 1; for(int i=1;i<=n;i++){ for(int j=1;j<=Math.min(i,k);j++){ dp[i][j] = dp[i-1][j-1]; if(i-1>=j) dp[i][j] += (i-1)*dp[i-1][j]; dp[i][j] %= MOD; } } return (int)dp[n][k]; } }
|
思考:如果题目要求左看为m,右看为n求组合数,如何解。斯特林数