代码随想录训练Day2[数组02]
209.长度最小的子数组
滑动窗口:
思路: 子数组的长度会不断变更, 可能在中间,可能 在两边,也可能在中间,所以要是值一个值和每次产生的子数组长度作比较。依旧是两重循环,一重循环来遍历整个数组,第二重循环,来寻找字串的位置。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int result_length = Integer.MAX_VALUE; // 设置数组的最大值,和子数组的大小做比较
int sums = 0 ;
int sun_length = 0;
int j = 0; // j 值 很关键 相当于后排的索引
for (int i = 0; i < nums.length; i++) { //我们先想第一次如何解, 再将 第一次中 的固定值 改为变量
sums += nums[i];
while (sums >= target) {
sun_length = i - j + 1; //yin
result_length = Integer.min(result_length,sun_length);
sums -= nums[j];
j++;
}
}
return result_length == Integer.MAX_VALUE ? 0 : result_length;
}
}
59.螺旋矩阵II
首先我没搞懂要循环几次,也就是while() 中的条件,应该是n/2 , 但首先考虑到n 分奇偶,如果是奇数,就会留下中间的位置,在最后判断如果是奇数就对填充的数组单独的赋值,也就是nums[n/2,n/2] = n* n;
然后是区间,选用左闭右开 但记住右开 区间的值就是 n -offset,记住这里是下标,填充元素一行不变,一行++,
class Solution {
public int[][] generateMatrix(int n) {
int curr = 0;
int cnt = 1;
int startx = 0;
int starty = 0;
int i = 0, j = 0;
int offset = 1;
int[][] result = new int[n][n];
while (curr <= n / 2) { //确定循环圈数 首先考虑到奇偶的 如果是奇数的话就将其放到最后填充
//j 的开始一定是startx 计数 内圈的时候 起始值就不一样了 对应下面的startxy
for (j = starty; j < n - offset; j++) {
result[startx][j] = cnt++;
}
for (i = startx; i < n - offset; i++) {
result[i][j] = cnt++;
}
for(; j > starty ; j--){
result[i][j] = cnt++;
}
for (; i > startx ; i--){
result[i][j] = cnt++;
}
offset ++;
startx++;
starty++;
curr++;
}
//最后对奇偶进行判断
if (n % 2 != 0){
result[i][j]= n*n;
}
return result;
}
}
好吧第一次接触ACM模式还是有点吃惊的,啥都没有全要自己写,我都忘记怎么写mian,这题正好熟悉一下。
前缀和:理解了不难,但第一次有点难想,还是想会用两个索引,从a 加到b ,实际做完,发现最后还有边界要考虑
要将a = 0单独考虑,这个区间是左包右包的所以要将a 的上一个值去掉
记住模板吧! 要不然遇到ACM 就gg
import java.util.*;
public class Main
{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] array = new int[n];
int[] sumArry = new int[n];
int sum = 0; //用来解决数组越界问题
for(int i = 0 ; i < n ; i ++ ){
array[i] = scanner.nextInt();
//这里第一次如何处理 数组越界问题
sum += array[i];
sumArry[i] = sum;
}
int a ;
int b ;
while (scanner.hasNextInt()) {
//这里注意数组从0 开始数
a = scanner.nextInt();
b = scanner.nextInt();
//界定一下边界条件
if( a == 0 ){
sum = sumArry[b];
}else{
//区间是包含两边的 当输入的是1 就要将1 之前的值0 去掉
sum = sumArry[b] - sumArry[a - 1];
}
System.out.println(sum);
}
scanner.close();
}
}
在一个城市区域内,被划分成了n * m个连续的区块,每个区块都拥有不同的权值,代表着其土地价值。目前,有两家开发公司,A 公司和 B 公司,希望购买这个城市区域的土地。
现在,需要将这个城市区域的所有区块分配给 A 公司和 B 公司。
然而,由于城市规划的限制,只允许将区域按横向或纵向划分成两个子区域,而且每个子区域都必须包含一个或多个区块。 为了确保公平竞争,你需要找到一种分配方式,使得 A 公司和 B 公司各自的子区域内的土地总价值之差最小。
注意:区块不可再分。
import java.util.*;
public class Main{
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
int sum = 0;
int[][] place = new int[n][m];
for(int i = 0 ; i < n ; i++)
{
for(int j = 0 ; j < m ; j++){
place[i][j] = scanner.nextInt();
sum += place[i][j];
}
}
//横向统计: 只有单列
int[] sumy = new int[n];
for(int i = 0 ; i < n ; i++){
for(int j = 0 ;j < m; j++){
sumy[i] += place[i][j];
}
}
int[] sumx = new int[m];
for(int j = 0 ;j < m ; j++){
for(int i = 0 ; i < n ;i++){
sumx[j] += place[i][j];
}
}
//这里将行和列分开分别做了前缀
int result = Integer.MAX_VALUE;
int y = 0;
for(int i = 0; i < n ;i++){
y += sumy[i];
result = Math.min(result, Math.abs((sum - y) - y));
}
int x = 0;
for(int j = 0; j < m ; j++){
x += sumx[j];
result = Math.min(result, Math.abs((sum - x) - x));
}
System.out.println(result);
scanner.close();
}
}