You are on page 1of 15

Q1: 1798 · Minimum Cost to Merge Stones

SOLUTION1:

public class Solution {


/**
* @param stones:
* @param K:
* @return: return a integer
*/
public int mergeStones(int[] stones, int K) {
// write your code here
int n = stones.length;
if ((n - 1) % (K - 1) != 0) {
return -1;
}

int[] sum = new int[n + 1];


sum[0] = 0;
for (int i = 1; i <= n; ++i) {
sum[i] = sum[i - 1] + stones[i - 1];
}

int[][][] dp = new int[n][n][K + 1];


for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
for (int k = 0; k <= K; ++k) {
dp[i][j][k] = Integer.MAX_VALUE;
}
}
}

for (int i = 0; i < n; ++i) {


dp[i][i][1] = 0;
}

for (int len = 2; len <= n; ++len) {


for (int i = 0; i + len <= n; ++i) {
int j = i + len - 1;
for (int k = 2; k <= K; ++k) {
//这是一个加速, 中间大部分都是没有解的。
for (int m = i; m < j; m += K - 1) {
dp[i][j][k] = Math.min(dp[i][j][k], dp[i][m][1] + dp[m + 1]
[j][k - 1]);
}
}
dp[i][j][1] = dp[i][j][K] + sum[j + 1] - sum[i];
}
}
return dp[0][n - 1][1];
}
}

SOLUTION 2

PYTHON

class Solution:
"""
@param stones:
@param K:
@return: return a integer
"""
def mergeStones(self, stones, K):
n = len(stones)

if (n - 1) % (K - 1) != 0:
return -1

f = [[0 for _ in range(n)] for _ in range(n)]

prefix = [0 for _ in range(n + 1)]


for i in range(n):
prefix[i + 1] = prefix[i] + stones[i]

for l in range(K, n + 1):


for i in range(n - l + 1):
j = i + l - 1
f[i][j] = sys.maxsize
for m in range(i, j, K - 1):
f[i][j] = min(f[i][j], f[i][m] + f[m + 1][j])
if (j - i) % (K - 1) == 0:
f[i][j] += prefix[j + 1] - prefix[i]

return f[0][n - 1]
SOLUTION 3:JAVA
public class Solution {
/**
* @param stones:
* @param K:
* @return: return a integer
*/
public int mergeStones(int[] stones, int k) {
// write your code here
if (stones.length <= 1) {
return 0;
}
if ((stones.length - 1) % (k - 1) != 0) {
return -1;
}
int n = stones.length;

int[] sum = new int[n + 1];


sum[0] = 0;
for (int i = 1; i <= n; i++) {
sum[i] = sum[i - 1] + stones[i - 1];
}

int[][] f = new int[n][n]; //(合并下标从 i~j 的区间剩余 1 堆)的总开销


for (int i = 0; i < n; i++) {
f[i][i] = 0;
}

for (int len = 2; len <= n; len++) {


for (int i = 0; i + len - 1 < n; i++) {
int j = i + len - 1;
f[i][j] = Integer.MAX_VALUE;
for (int m = i; m < j; m += (k - 1)) {
f[i][j] = Math.min(f[i][j], f[i][m] + f[m + 1][j]);
}
if ((len - k) % (k - 1) == 0) {
f[i][j] += sum[j + 1] - sum[i];
}
}
}

return f[0][n - 1];


}
}

SOLUTION 4:PYTHON
class Solution:
"""
@param stones:
@param K:
@return: return a integer
"""
def mergeStones(self, stones, K):
n = len(stones)

if (n - 1) % (K - 1) != 0:
return -1

# preprocessing
prefix_sum = self.get_prefix_sum(stones)

# state: dp[i][j][k] i 到 j 这一段合并为 k 堆石子的最小代价


dp = [[
[float('inf')] * (K + 1)
for _ in range(n)
] for __ in range(n)]

# initialization: 一开始所有石子各自为一堆,代价为 0
for i in range(n):
dp[i][i][1] = 0

# function:
# dp[i][j][k] = min{dp[i][x][k - 1] + dp[x + 1][j][1]} // for k > 1
# dp[i][j][1] = dp[i][j][K] + sum(stones[i..j]) // for k = 1
for i in range(n - 2, -1, -1):
for j in range(i + 1, n):
for k in range(2, K + 1):
for x in range(i, j):
dp[i][j][k] = min(dp[i][j][k], dp[i][x][k - 1] + dp[x + 1][j]
[1])
dp[i][j][1] = dp[i][j][K] + prefix_sum[j + 1] - prefix_sum[i]

# answer: dp[0][n - 1][1]


return -1 if dp[0][n - 1][1] == float('inf') else dp[0][n - 1][1]

def get_prefix_sum(self, A):


prefix_sum = [0]
for a in A:
prefix_sum.append(prefix_sum[-1] + a)
return prefix_sum
SOLUTION 5 PYTHON
from sys import maxsize

class Solution:
"""
@param stones:
@param K:
@return: return a integer
"""
def mergeStones(self, stones, K):
n = len(stones)

memo = [[[maxsize for _ in range(K + 1)] for _ in range(n)] for _ in


range(n)]

range_sum = self.get_range_sum(stones, n)

return self.memo_search(range_sum, 0, n - 1, 1, K, memo)

def memo_search(self, range_sum, left, right, k, K, memo):


if memo[left][right][k] != maxsize:
return memo[left][right][k]

if left == right:
if k == 1: return 0
return -1

if k == 1:
result = self.memo_search(range_sum, left, right, K, K, memo)
if result == -1:
return -1
return result + range_sum[left][right]

minimum = maxsize
for i in range(left, right - k + 2):
first_part = self.memo_search(range_sum, left, i, 1, K, memo)
rest_parts = self.memo_search(range_sum, i + 1, right, k - 1, K, memo)
if first_part == -1 or rest_parts == -1:
continue
minimum = min(minimum, first_part + rest_parts)

if minimum == maxsize: minimum = -1


memo[left][right][k] = minimum
return minimum

def get_range_sum(self, stones, n):


range_sum = [[0 for _ in range(n)] for _ in range(n)]

for i in range(n):
range_sum[i][i] = stones[i]

for i in range(n - 1, -1, -1):


for j in range(i + 1, n):
range_sum[i][j] = range_sum[i][j - 1] + stones[j]

return range_sum
SOLUTION 6:JAVA
public class Solution {
/**
* @param stones:
* @param K:
* @return: return a integer
*/
public int mergeStones(int[] stones, int K) {
int n = stones.length;

if ((n - 1) % (K - 1) != 0) {
return -1;
}

// preprocessing
int[] prefixSum = getPrefixSum(stones);

// state: dp[i][j][k] i 到 j 这一段合并为 k 堆石子的最小代价


int[][][] dp = new int[n][n][K + 1];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k <= K; k++) {
dp[i][j][k] = Integer.MAX_VALUE / 4;
}
}
}

// initialization: 一开始所有石子各自为一堆,代价为 0
for (int i = 0; i < n; i++) {
dp[i][i][1] = 0;
}

// function:
// dp[i][j][k] = min{dp[i][x][k - 1] + dp[x + 1][j][1]} // for k > 1
// dp[i][j][1] = dp[i][j][K] + sum(stones[i..j]) // for k = 1
for (int i = n - 2; i >= 0; i--) {
for (int j = i + 1; j < n; j++) {
for (int k = 2; k <= K; k++) {
for (int x = i; x < j; x++) {
dp[i][j][k] = Math.min(dp[i][j][k], dp[i][x][k - 1] + dp[x +
1][j][1]);
}
}
dp[i][j][1] = dp[i][j][K] + prefixSum[j + 1] - prefixSum[i];
}
}

// answer: dp[0][n - 1][1]


if (dp[0][n - 1][1] == Integer.MAX_VALUE) {
return -1;
}
return dp[0][n - 1][1];

}
private int[] getPrefixSum(int[] A) {
int[] prefixSum = new int[A.length + 1];
for (int i = 1; i <= A.length; i++) {
prefixSum[i] = prefixSum[i - 1] + A[i - 1];
}
return prefixSum;
}
}
Q2: 1890 · Form Minimum Number

SOLUTION:1

JAVA

public class Solution {


/**
* @param str: the pattern
* @return: the minimum number
*/
public String formMinimumNumber(String str) {

int length = str.length();


String answer = new String();
for (int i = 0; i <= length; i++) {
answer += ' ';
}
StringBuilder strBuilder = new StringBuilder(answer);
int count = 1;
for (int i = 0; i <= length; i++) {
if (i == length || str.charAt(i) == 'I') {
for (int j = i - 1 ; j >= -1 ; j--) {
strBuilder.setCharAt(j + 1, (char)('0' + count++));
if(j >= 0 && str.charAt(j) == 'I') {
break;
}
}
}
}

answer = strBuilder.toString();
return answer;
}
}
SOLUTION2: class Solution:
"""
@param str: the pattern
@return: the minimum number
"""
def formMinimumNumber(self, str):

length = len(str);
answer = " " * length;
count = 1;
for i in range(length + 1):
if i == length or str[i] == 'I':
for j in range(i - 1, -2, -1):
answer = answer[:j + 1] + chr(ord('0') + count) + answer[j + 2:];
count += 1;
if j >= 0 and str[j] == 'I':
break;

return answer;
SOLUTION: 3

C++

class Solution {
public:
/**
* @param str: the pattern
* @return: the minimum number
*/
string formMinimumNumber(string &str) {

int length = str.length();


string answer(length + 1, ' ');
int count = 1;
for (int i = 0; i <= length; i++) {
if (i == length || str[i] == 'I') {
for (int j = i - 1; j >= -1; j--) {
answer[j + 1] = '0' + count++;
if(j >= 0 && str[j] == 'I')
break;
}
}
}

return answer;
}
};
SOLUTION 4:

public String formMinimumNumber(String str) {

List<Integer> result = new ArrayList<>(str.length()+1);

List<Integer> list = new ArrayList<>(9);


for(int i=1;i<=9;i++){
list.add(i);
}

fill(str, result, list, str.length());

if(str.charAt(str.length()-1) == 'I'){
result.add(findAndRemove(list));
}

StringBuilder builder = new StringBuilder();

for(int i : result){
builder.append(i);
}
return builder.toString();
}

private void fill(String str, List<Integer> result, List<Integer> list, int size){
if(str.length() == 0 || result.size() == size){
return;
}

int firstI = str.indexOf("I");

if(firstI == -1){
firstI = str.length();
}

int last = result.size();

for(int i=0;i <= firstI; i++){


result.add(last, findAndRemove(list));
}

if(firstI < str.length()){


fill(str.substring(firstI+1), result, list, size);
}

private Integer findAndRemove(List<Integer> left){

int ret = left.get(0);


if(left.size() == 1){
return ret;
}

for(int i:left){
ret = Math.min(ret, i);
}

left.remove(new Integer(ret));
return ret;
}

}
SOLUTION 5: PYTHON

class Solution:
"""
@param str: the pattern
@return: the minimum number
"""
def formMinimumNumber(self, string):
# Write your code here.
n = len(string)
answer = [str(i) for i in range(1, n + 2)]
i = 0
while i < n:
if string[i] == 'D':
j = i
while j < n and string[j] == 'D':
j += 1
self.swap(answer, i, j)
i = j
else:
i += 1

return ''.join(answer)

def swap(self, answer, i, j):


while i <= j:
answer[i], answer[j] = answer[j], answer[i]
i += 1
j -= 1

SOLUTION 6:PYTHON

class Solution:
"""
@param str: the pattern
@return: the minimum number
"""
def formMinimumNumber(self, S):

l = len(S)
S += "I"
res = [-1 for _ in range(l+1)]
count = 1
for i in range(l + 1):
if i == l or S[i] == "I":
for j in range(i,-1,-1):
if res[j] != -1:
break
res[j] = str(count)
count += 1

return "".join(res)
SOLUTION 7:C++

public class Solution {


/**
* @param str: the pattern
* @return: the minimum number
*/
public String formMinimumNumber(String str) {
// Write your code here.
int n = str.length();
String ans = new String();
for (int i = 0;i <= n;i++){
ans += ' ';
}
StringBuilder strBuilder = new StringBuilder(ans);
int count = 1;
for (int i = 0; i <= n; i++)
{
if (i == n || str.charAt(i) == 'I')
{
for (int j = i - 1 ; j >= -1 ; j--)
{
strBuilder.setCharAt(j + 1, (char)('0' + count++));
if(j >= 0 && str.charAt(j) == 'I')
break;
}
}
}
ans = strBuilder.toString();
return ans;
}
}
SOLUTION 8 C++;

public class Solution {


/**
* @param str: the pattern
* @return: the minimum number
*/
public String formMinimumNumber(String str) {
// Write your code here.
int n = str.length();
String ans = new String();
for (int i = 0;i <= n;i++){
ans += ' ';
}
StringBuilder strBuilder = new StringBuilder(ans);
int count = 1;
for (int i = 0; i <= n; i++)
{
if (i == n || str.charAt(i) == 'I')
{
for (int j = i - 1 ; j >= -1 ; j--)
{
strBuilder.setCharAt(j + 1, (char)('0' + count++));
if(j >= 0 && str.charAt(j) == 'I')
break;
}
}
}
ans = strBuilder.toString();
return ans;
}
}
Q3: 1872 · Minimum Cost to Connect Sticks

SOLUTION 1 C++

class Solution {
public:
/**
* @param sticks: the length of sticks
* @return: Minimum Cost to Connect Sticks
*/
int MinimumCost(vector<int> &sticks) {
if (sticks.size() < 2) {
return 0;
}
priority_queue<int, vector<int>, greater<int> > minheap;
for (int num:sticks) {
minheap.push(num);
}
int res=0;
while (minheap.size() > 1) {
int merge = minheap.top();
minheap.pop();
merge += minheap.top();
minheap.pop();
res += merge;
minheap.push(merge);
}
return res;
}
};

SOLUTION 2 C++
class Solution {
public:
/**
* @param sticks: the length of sticks
* @return: Minimum Cost to Connect Sticks
*/
int MinimumCost(vector<int> &sticks) {
sort(sticks.begin(),sticks.end());
queue<int> q1,q2;
for (int i : sticks) {
q1.push(i);
}
int res = 0,merge;
while(q1.size() + q2.size() > 1){
if(q2.empty()){
merge = q1.front();
q1.pop();
merge += q1.front();
q1.pop();
q2.push(merge);
res += merge;
}
else if (q1.empty()){
merge = q2.front();
q2.pop();
merge += q2.front();
q2.pop();
q2.push(merge);
res+=merge;
}
else {
if(q1.front() > q2.front()){
merge = q2.front();
q2.pop();
}
else {
merge = q1.front();
q1.pop();
}

if (q1.empty()){
merge += q2.front();
q2.pop();
q2.push(merge);
res += merge;
}
else if(q2.empty()){
merge += q1.front();
q1.pop();
q2.push(merge);
res += merge;
}
else {
if(q1.front() > q2.front()){
merge += q2.front();
q2.pop();
q2.push(merge);
res += merge;
}
else {
merge += q1.front();
q1.pop();
q2.push(merge);
res += merge;
}
}
}
}
return res;

}
};
SOLUTION 3
# minheap 暴力
# 直接将所有值压入 minheap,每次取前两个值相加成 merge,同时将 merge 压入 minheap
class Solution:
"""
@param sticks: the length of sticks
@return: Minimum Cost to Connect Sticks
"""
def MinimumCost(self, sticks):
import queue
if len(sticks) < 2:
return 0
minheap = queue.PriorityQueue()
for num in sticks:
minheap.put(num)
res = 0
while (minheap.qsize() > 1):
merge = minheap.get() + minheap.get()
res += merge
minheap.put(merge)
return res

# 排序,双队列
# 先将数组排序,然后开始合并,合并后的值放入 q2 末尾,能够保证 q2 中被押入的值是
# 一定大于前面的值的,每次合并我们考虑 q1,q2 非空以及比较 q1[0]和 q2[0]的大小
import collections
class Solution:
"""
@param sticks: the length of sticks
@return: Minimum Cost to Connect Sticks
"""
def MinimumCost(self, sticks):
sticks = sorted(sticks)
q1 = collections.deque()
q2 = collections.deque()
for num in sticks:
q1.append(num)
res,merge = 0,0
while len(q1) + len(q2) > 1:
if len(q2) == 0:
merge = q1.popleft()
merge += q1.popleft()
q2.append(merge)
res += merge
elif len(q1) == 0:
merge = q2.popleft()
merge += q2.popleft()
q2.append(merge)
res += merge
else:
if q1[0] > q2[0]:
merge = q2.popleft()
else:
merge = q1.popleft()

if len(q1) == 0:
merge += q2.popleft()
q2.append(merge)
res += merge
elif len(q2) == 0:
merge += q1.popleft()
q2.append(merge)
res += merge
else:
if q1[0] > q2[0]:
merge += q2.popleft()
q2.append(merge)
res += merge
else:
merge += q1.popleft()
q2.append(merge)
res += merge
return res;
SOLUTION 4:

import heapq

class Solution:
"""
@param sticks: the length of sticks
@return: Minimum Cost to Connect Sticks
"""
def MinimumCost(self, sticks):
heap = []
for stick in sticks:
heapq.heappush(heap, stick)

result = 0
while len(heap) > 1:
a = heapq.heappop(heap)
b = heapq.heappop(heap)
result += a + b
heapq.heappush(heap, a + b)
return result
Q4:

You might also like