You are given nums
, an array of positive integers of size 2 * n
. You must perform n
operations on this array.
In the ith
operation (1-indexed), you will:
- Choose two elements,
x
andy
. - Receive a score of
i * gcd(x, y)
. - Remove
x
andy
fromnums
.
Return the maximum score you can receive after performing n
operations.
The function gcd(x, y)
is the greatest common divisor of x
and y
.
Example 1:
Input: nums = [1,2]
Output: 1
Explanation: The optimal choice of operations is:
(1 * gcd(1, 2)) = 1
Example 2:
Input: nums = [3,4,6,8]
Output: 11
Explanation: The optimal choice of operations is:
(1 * gcd(3, 6)) + (2 * gcd(4, 8)) = 3 + 8 = 11
Example 3:
Input: nums = [1,2,3,4,5,6] Output: 14 Explanation: The optimal choice of operations is: (1 * gcd(1, 5)) + (2 * gcd(2, 4)) + (3 * gcd(3, 6)) = 1 + 4 + 9 = 14
忘了怎么求全部方案中的最大值,囧
先用回溯法求出所有解,然后每次都保留max,从而取最大值。有道理啊
//https://leetcode.com/problems/maximize-score-after-n-operations/discuss/1200095/Java-Backtrack-with-memoization
class Solution {
int res;
int n;
HashMap<String, Integer> memo;
public int maxScore(int[] nums) {
res = 0;
n = nums.length/2;
memo = new HashMap<>();
return backtrack(nums, 1, new HashSet<>());
//return res;
}
private int backtrack(int [] nums, int i, HashSet<Integer> set) {
if(i > n) {
return 0;
}
String key = convert(i,set);
System.out.println("key是i加上set = " + key);
//就是先判断一下有没有进行到过这一步,有的话就取出来
if(memo.containsKey(key)) {
return memo.get(key);
}
int val=0, res=0;
for(int j=0; j<nums.length; j++) {
if(!set.contains(j)) {
for(int k=j+1; k<nums.length; k++) {
val=0;
if(!set.contains(k)) {
set.add(j); set.add(k);
val = i * (gcd(nums[j], nums[k])) + backtrack(nums, i+1, set);
//每次都只保留最大值
res = Math.max(res, val);
set.remove(j); set.remove(k);
}
}
}
}
memo.put(key, res);
return res;
}
private int gcd(int a, int b) {
return (a%b)==0 ? b : gcd(b, a%b);
}
private String convert(int i, HashSet<Integer> set) {
return Integer.toString(i) + set.toString();
}
}