https://chowdera.com/2021/03/20210326160903226c.html
Give you a length of n Binary string of boxes , among boxes[i] The value of is '0' It means the first one i A box is empty Of , and boxes[i] The value of is '1' There is... In the box One Pellet .
In one step , You can take One The ball moves from a box to an adjacent box . The first i A box and j Two adjacent boxes need to satisfy abs(i - j) == 1 . Be careful , After operation , There may be more than one ball in some boxes .
Returns a length of n Array of answer , among answer[i] It's moving all the balls to the second i What a box needs Minimum Operands .
Every answer[i] It all depends on the box The initial state Calculate .
    public int[] minOperations(String boxes) {
        int n = boxes.length();
        int[] left = new int[n];
        int[] right = new int[n];
        int[] ans = new int[n];
        int count = boxes.charAt(0) - '0';
        for(int i = 1 ; i < n ; i++){
            left[i] = left[i - 1] + count;
            count += boxes.charAt(i) - '0';
        }
        count = boxes.charAt(n - 1) - '0';
        for(int i = n - 2 ; i >=0 ; i--){
            right[i] = right[i + 1] + count;
            count += boxes.charAt(i) - '0';
        }
		
        for(int i = 0 ; i < n ; i++) {
            ans[i] = left[i] + right[i];
        }
        return ans;
    }answer array, we won't consider that space in complexity analysis and hence space complexity is constant.  public int[] minOperations(String boxes) {        
        int[] ans = new int[boxes.length()];
		int cnt = boxes.charAt(0) - '0';
		for(int i=1;i<boxes.length(); i++) {
			ans[i] = ans[i-1] + cnt;
			cnt += boxes.charAt(i) - '0';
		}
		
		int runner = 0; 
		cnt = boxes.charAt(boxes.length()-1) - '0';
		for(int i=boxes.length()-2;i>=0; i--) {
			runner += cnt; 
			ans[i] += runner;
			cnt += boxes.charAt(i) - '0'; 
		}
        return ans;  
  }public int[] minOperations(String boxes) {
    int left = 0, right = 0, lsum = 0, rsum = 0, len = boxes.length();
	for (int i = 0; i < len; i++) {
		if (boxes.charAt(i) == '1') {
			right++;
			rsum += i;
		}
	}
	int[] ans = new int[len];
	for (int i = 0; i < len; i++) {
		ans[i] = lsum + rsum;
		if (boxes.charAt(i) == '1') {
			left++;
			right--;
		}
		lsum = lsum + left;
		rsum = rsum - right;
	}
	return ans;
}We first "move" balls from left to right, and track how many ops it takes for each box.
For that, we count how many balls we got so far in cnt, and accumulate it in ops.
Then, we do the same from right to left.
public int[] minOperations(String boxes) {
    int[] res = new int[boxes.length()];
    for (int i = 0, ops = 0, cnt = 0; i < boxes.length(); ++i) {
       res[i] += ops;
       cnt += boxes.charAt(i) == '1' ? 1 : 0;
       ops += cnt;
    }    
    for (int i = boxes.length() - 1, ops = 0, cnt = 0; i >= 0; --i) {
        res[i] += ops;
        cnt += boxes.charAt(i) == '1' ? 1 : 0;
        ops += cnt;
    }
    return res;
}What needs to be considered is , How to move to by all x The number of operations answer[x] Find all move to x+1 The number of operations answer[x+1]. about x+1 The ball on the left , Each ball will be operated once more , about x The ball on the right , Each will operate less than once . So , You just have to figure out x+1 The number of balls on the left side left(x+1) and x The number of balls on the right right(x) that will do . That is to say answer[x+1]=answer[x]+left(x+1)-right(x).
At present, we don't have to ask for it every time left and right, Save the position of the ball in line , Compare the current position and x,x+1 The relationship between , It can be calculated directly left and right The change of , But this code is easier to understand . You can try to optimize it yourself .
vector<int> minOperations(string boxes) { vector<int> positions; int n = boxes.size(); vector<int> answer(n, 0); for (int i = 0; i < n; i++) { if (boxes[i] == '1') { positions.push_back(i); if (i) answer[0] += i; } } for (int i = 1; i < n; i++) { // answer[i]=answer[i-1]+left(i)-right(i-1) int left = lower_bound(positions.begin(), positions.end(), i) - positions.begin(); int right = positions.end() - upper_bound(positions.begin(), positions.end(), i - 1); answer[i] = answer[i - 1] + left - right; } return answer; }
https://www.taodudu.cc/news/show-2114813.html
这个思路是:我们先找到把所有的 1 移到下标为 0 的起始位置需要的最小操作数为 r e s [ 0 ] res[0] res[0]。然后其余把所有 1 移到 i i i 位置的操作数 = 把所有 1 移到 i − 1 i - 1 i−1 位置的的操作数 -(右边的所有 1) + (左边的所有 1),即转移方程是:
r e s [ i ] = r e s [ i − 1 ] − ( o n e s − v i s i t e d ) + v i s i t e d res[i] = res[i - 1] - (ones - visited) + visited res[i]=res[i−1]−(ones−visited)+visited
原理是什么呢?因为把所有位置移动到 r e s [ i ] res[i] res[i] 位置相对于 r e s [ i − 1 ] res[i - 1] res[i−1] 位置来说,所有它右边位置的 1 少移动了一次,它左边位置的 1 多移动了一次。
时间复杂度: O ( N ) O(N) O(N),空间复杂度: O ( 1 ) O(1) O(1).
    vector<int> minOperations(string boxes) {
        vector<int> result(size(boxes)); 
        for (int i = 0, accu = 0, cnt = 0; i < size(boxes); ++i) {
           result[i] += accu;
           cnt += (boxes[i] == '1') ? 1 : 0;
           accu += cnt;
        }
        for (int i = size(boxes) - 1, accu = 0, cnt = 0; i >= 0; --i) {
            result[i] += accu;
            cnt += (boxes[i] == '1') ? 1 : 0;
            accu += cnt;
        }
        return result;
    }
X.
https://www.taodudu.cc/news/show-2114813.html
本题的数据规模为 2000,用 O ( N 2 ) O(N^2) O(N2) 的解法竟然能过。这个方法比较简单,直接对每个位置向左右两边统计具体各个 1 的位置之和。
    def minOperations(self, boxes: str) -> List[int]:
        N = len(boxes)
        res = [0] * N
        for i in range(N):
            left = [i - j for j in range(i) if boxes[j] == "1"]
            right = [j - i for j in range(i + 1, N) if boxes[j] == "1"]
            res[i] = sum(left) + sum(right)
        return reshttps://kickstart.best/1769-minimum-number-of-operations-to-move-all-balls-to-each-box/