题目
思路
以单组数据来看,对于给定数组nums,是否存在连续和能够被指定k整除?可以想到一下几种方案:
- 暴力破解
- 组合思想
- 前缀和
思路一:暴力破解
思路二:组合思想
思路三:前缀和
参考leetcode原题:974. 和可被 K 整除的子数组
leetcode的题目考虑了负数,虽然本题的牌的数字不会有正数,但这里还是对正负数都考虑进来。
题解
给出了三种思路在本题的具体实现,前缀和确实很抽象,也不好表达,对此不理解的多看看974. 和可被 K 整除的子数组的题解
package hwod;
import java.util.*;
import java.util.stream.Collectors;
public class NumberGame {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
List<Integer> list1 = new ArrayList<>();//存放给定的牌
List<List<Integer>> list2 = new ArrayList<>();//牌堆
while (sc.hasNextLine()) {
String firstLines = sc.nextLine();
if ("".equals(firstLines)) break;
list1.add(Arrays.stream(firstLines.split(" ")).mapToInt(Integer::parseInt).toArray()[1]);
String secondLines = sc.nextLine();
list2.add(Arrays.stream(secondLines.split(" ")).mapToInt(Integer::parseInt).boxed().collect(Collectors.toList()));
}
List<Integer> res = numberGame(list1, list2);
for (Integer re : res) {
System.out.println(re);
}
}
private static List<Integer> numberGame(List<Integer> list1, List<List<Integer>> list2) {
List<Integer> res = new ArrayList<>();
for (int i = 0; i < list1.size(); i++) {
res.add(checked3(list2.get(i), list1.get(i)));
}
return res;
}
/**
* 暴力破解
* @param list 牌堆
* @param target 被除的值
* @return 如果存在连续和能够整除target,返回1,否则返回0
*/
private static int checked(List<Integer> list, Integer target) {
for (int i = 0; i < list.size(); i++) {
int sum = 0;
for (int j = i; j < list.size(); j++) {
sum += list.get(j);
if (sum % target == 0) return 1;
}
}
return 0;
}
private static int res = 0;
/**
* 组合思想
* @param list
* @param target
* @return
*/
private static int checked2(List<Integer> list, Integer target) {
LinkedList<Integer> path = new LinkedList<>();
dfs(list, 0, path, 0, target);
return res;
}
private static void dfs(List<Integer> list, int start, LinkedList<Integer> path, int sum, int k) {
if (!path.isEmpty() && sum % k == 0) {
res = 1;
return;
}
for (int i = start; i < list.size(); i++) {
if (!path.isEmpty() && path.peekLast() != i - 1) continue;
if (res != 0) break;
path.addLast(i);
dfs(list, i + 1, path, sum + list.get(i), k);
path.removeLast();
}
}
/**
* 设P[i]为前i项的前缀和
* sum(i,j)=num[i]+num[i+1]+...+num[j]=P[j]-p[i-1]
* (P[j]-p[i])%k==0 ==> (P[j]%k - p[i-1]%k)%k=0
*
* @param list
* @param k
* @return 如果存在连续和能够整除k,返回1,否则返回0
*/
private static int checked3(List<Integer> list, Integer k) {
int[] dp = new int[k];
dp[0] = 1;
int sum = 0;
for (int i = 0; i < list.size(); i++) {
sum += list.get(i);
int mod = (sum % k + k) % k;
if (dp[mod] != 0) return 1;
dp[mod]++;
}
return 0;
}
}
推荐
如果你对本系列的其他题目感兴趣,可以参考华为OD机试真题及题解(JAVA),查看当前专栏更新的所有题目。