最近小明搬到了新家,他正在粉刷墙壁,但是不幸的是他粉刷的墙壁并不理想。他的墙壁是一个长度为 的格子,每个格子用0表示红色,用1表示蓝色。现在墙壁是一个非常混乱的颜色。他想将墙壁涂成左边全是蓝色右边全是红色,可以将墙壁刷成全是红色或者蓝色。请问他至少需要粉刷多少个格子墙壁刷成他想要的样子?
数据范围:
进阶:时间复杂度,空间复杂度
第一行一个整数。
第二行个长度为的01串,0表示红色,1表示蓝色。
输出一个整数表示最少粉刷次数。
3 001
1
只需要将最后一个刷成红色。
import java.io.*; import java.util.*; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); char[] wall = br.readLine().toCharArray(); int[] left = new int[n]; // 包括自己,左边0的个数,这些是要被刷成1的 int[] right = new int[n]; // 包括自己,右边1的个数,这些是要被刷成0的 for(int i = 0; i < n; i++){ if(i == 0){ left[i] = wall[i] == '0'? 1: 0; right[n - i - 1] = wall[n - i - 1] == '1'? 1: 0; }else{ left[i] = left[i - 1] + (wall[i] == '0'? 1: 0); right[n - i - 1] = right[n - i] + (wall[n - i - 1] == '1'? 1: 0); } } int cost = n; for(int i = 0; i < n; i++){ cost = Math.min(cost, left[i] + right[i] - 1); } System.out.println(cost); } }
import java.util.*; public class Main{ public static void main(String[] args){ Scanner in = new Scanner(System.in); int n = in.nextInt(); in.nextLine(); String s = in.nextLine(); int len = s.length(); int count = 0; int min = len; for(int i = 0; i < len; i++){ // 遍历统计1的个数 if(s.charAt(i) == '1'){ count++; } } min = Math.min(count,n-count); // 全刷成一种颜色,需要的最小次数 int left1 = 0; for(int i = 0; i < len; i++){ // 再次遍历,把第i个元素当成分割点(包括i) if(s.charAt(i) == '1'){ left1++; // i左边的1个数(包括i),则左边0个数有:(i+1)-left1 【即左边总元素个数-1的个数】,这些0需要刷成1 } // 则右边还有count-left1个1,这些1需要刷成0, int sum = i + 1 - left1 + count - left1; if(sum < min){ // 所以总共需要刷 (i+1)-left1 + count - left1 min = sum; // 保存最小刷新次数 } } System.out.println(min); } }
考虑第 个格子的左边线作为分界,左 1 右 0 ,左边假设全涂好了,右边
假如 第 i + 1 个房间是 1,那现在就不用涂了,反之要补上。
DP 的初值是一共几个 1
dp[i] 的意义是,选第 i 个时的花费。最后取 min 即可
input() room = input() dp = [0] * (1 + len(room)) dp[0] = room.count("1") for i in range(1, len(room) + 1): dp[i] = dp[i - 1] + int(room[i - 1] == "0") - int(room[i - 1] == "1") print(min(dp))
JAVA 两个最简单的【动态规划】
import java.util.*; import java.io.*; public class Main{ int paint(int length, int[] array){ int[] dp = new int[length], min = new int[length+1]; dp[0] = array[0]; for(int i = 1 ; i<length ; i++) dp[i] = dp[i-1] + array[i]; min[0] = dp[length - 1]; //左边留0个墙面刷蓝,右边剩余所有墙面刷红(即1的个数) for(int i = 1 ; i<=length ; i++) min[i] = Math.min(min[i-1], (i - dp[i-1]) + (dp[length-1] - dp[i-1])); return min[length]; } // 单纯处理输入数据,不用看 public static void main(String[] args) throws IOException{ Main main = new Main(); BufferedReader buf = new BufferedReader(new InputStreamReader(System.in)); int i = 0, len = Integer.parseInt(buf.readLine()); int[] ar = new int[len]; for(char c : buf.readLine().toCharArray()){ ar[i] = c - '0'; i++; } System.out.println(main.paint(len, ar)); } }
string str; int num; cin>>num>>str int numRightAll_0 = 0; int numLeftAll_1 = 0; for(int i=0; i<num; i++){ if(str[i] != '0') numRightAll_0++; } int minNum = numRightAll_0; for(int i=0; i<num; i++){ if (str[i] != '0'){ numRightAll_0--; } else{ numLeftAll_1++; } minNum = min(minNum, numRightAll_0 + numLeftAll_1); } cout<<minNum<<endl;
#include<iostream> #include<string> #include<cmath> using namespace std; int main(){ int n; cin>>n; string s; cin>>s; int array[n]; int sum=0; for(int i=0;i<n;i++){ array[i]=s[i]-'0'; sum=sum+array[i]; } int num=0; int nl=0,nr=sum; int ARRAY[n+1]; if(sum==0) cout<<num; else{ ARRAY[0]=nl+nr; for(int j=0;j<n;j++){ if (array[j]==0){ nl=nl+1; } else{ nr=nr-1; } ARRAY[j+1]=nl+nr; } num=ARRAY[0]; for(int a=1;a<n+1;a++){ if(ARRAY[a]<num) num=ARRAY[a]; } cout<<num; } }
import math class Solution: def solution(self, n: int, arr: str): pre_one = [0] * n pre_zero = [0] * n total_one = total_zero = 0 for i in range(n): if arr[i] =='1': total_one += 1 pre_one[i] = total_one if arr[i] == '0': total_zero += 1 pre_zero[i] = total_zero ans = math.inf for i in range(n): one = pre_one[i] zero = pre_zero[i] # left one right zero # left zero right one ans = min(ans, zero + total_one - one) ans = min(ans, total_one, total_zero) return ans if __name__=='__main__': n = int(input()) wall = input() solution = Solution() res = solution.solution(n, wall) print(res)
#include<vector> #include<iostream> #include<math.h> using namespace std; int test01(int n, string& s) { // 计算前i个格子中,蓝色格子的数量 vector<int> cnts(n + 1, 0); int c = 0; for (int i = 0; i < n; ++i) { if (s[i] == '1') { c++; } cnts[i + 1] = c; } // 初始时,将所有格子刷为红色 int res = cnts[n]; // 计算前i+1个格子,全部刷为蓝色的操作数 for (int i = 0; i < n; ++i) { int t = i + 1 - cnts[i + 1] + cnts[n] - cnts[i + 1]; res = min(res, t); } return res; } int main() { int n; string s; cin >> n; cin >> s; cout << test01(n, s) << endl;; return 0; }
public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int s1 = Integer.valueOf(scanner.nextLine()); String s2 = scanner.nextLine(); if (s2.startsWith("1") || s2.endsWith("0")) { System.out.println(0); return; } char[] ss = s2.toCharArray(); int start = -1, end = -1; for (int i = 0, j = ss.length - 1; i != j -1 || i < j; i++, j--) { if (ss[i] == '1') { start = i; break; } if (ss[j] == '0') { end = j; break; } } if (start == -1) { System.out.println(s1 - end - 1); } else if (end == -1) { System.out.println(start); } else { System.out.println(s1/2); } }
简单双指针
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = Integer.parseInt(sc.nextLine()); char[] cs = sc.nextLine().toCharArray(); sc.close(); int left0 = 0, left1 = 0; int right0 = 0, right1 = 0; for (int i = n - 1; i >= 0; i--) { if (cs[i] == '1') { right1++; } else { right0++; } } int min = right1; for (int i = 0; i < n; i++) { if (cs[i] == '1') { right1--; left1++; } else { left0++; right0--; } min = Math.min(min, left0 + right1); } System.out.println(min); } }
let n = Number(readline()) let rawStr = readline() let min = n let left0=0,right1=0 for(let i = 0;i<n;++i){ if(rawStr[i]=='1')++right1 } for(let i = 0;i<=n;++i){ if(i>0){ if(rawStr[i-1]=='0')left0++ else right1-- } if(left0+right1<min)min = left0+right1 } print(min)加一个隔板,从左到右遍历隔板的位置。首先隔板在最左边,进行初始化。隔板每向右移动一次,就更新left0的个数和right1的个数。复杂度是O(n)
import java.util.Arrays; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); sc.nextLine(); String s = sc.nextLine(); int[] dp = new int[n + 1]; int count = 0; for (char c : s.toCharArray()) { if (c == '1') { count++; } } dp[0] = count; for (int i = 1; i < n + 1; i++) { if (s.charAt(i - 1) == '0') { dp[i] = dp[i - 1] + 1; } else { dp[i] = dp[i - 1] - 1; } } System.out.println(Arrays.stream(dp).min().getAsInt()); } }
var n=parseInt(readline()) var str=readline() function rush(n,str){ str=str.split('') var arr0 = [] var arr1 = [] var count=0 var min =0 for(var i=0;i<n;i++){ if(str[i]=='1'){ arr1.push(str[i]) count++ } } min=Math.min(count,n-count) var left1=0 for(var i =0;i<n ;i++){ if(str[i]=='1'){ left1++ } var sum = i + 1-left1+count-left1 if(sum<min){ min=sum } } console.log(min); } rush(n,str)参考评论写了JS的代码,谢谢大佬