0% found this document useful (0 votes)
53 views15 pages

1798 Minimum Cost To Merge Stones: Public Class

The document contains 6 solutions to the problem of forming the minimum number from a pattern string. The solutions are in Java, Python, and C++. They use dynamic programming and prefix sums to build the minimum number string in one pass from left to right while incrementing a counter for each 'I' character.

Uploaded by

AAYUSH VATSA
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
53 views15 pages

1798 Minimum Cost To Merge Stones: Public Class

The document contains 6 solutions to the problem of forming the minimum number from a pattern string. The solutions are in Java, Python, and C++. They use dynamic programming and prefix sums to build the minimum number string in one pass from left to right while incrementing a counter for each 'I' character.

Uploaded by

AAYUSH VATSA
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 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