59. 螺旋矩阵 II
题目:
给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
示例 1:
输入: n = 3
输出: [[1,2,3],[8,9,4],[7,6,5]]
示例 2:
输入: n = 1
输出: [[1]]
思路:
先创建一个空的 nxn
的数组,通过上右下左四条边的循环遍历,将数字输入进去。首先要确定循环条件,因为是 n
维矩阵,也就只能旋转 n/2
圈,这里是循环条件,但是循环条件要不断减小,所以循环条件设置为 while (Math. floor (n/2) --)
,当它达到 while (0)
的时候会自动停止循环。接着确定如何创建空的矩阵,nxn
的矩阵需要通过 let nums = new Array (n). fill (0). map (()=>new Array (n). fill (0))
,这个代码的意思是创建一个长度为 n
的数组,并且将数组中的元素全部填充成 0
,接着用 map()
方法将数组中的每个元素都扩展成一个长度为 n
的矩阵,并且全部填充为 0
,这样就完成了 nxn
的数组的创建。接下来要设置遍历的起始点,从左上角开始,想象成一个矩阵,也就是 (i = 0 ,j = 0)
的位置,设置 startX = 0,startY = 0
。考虑到保证每一次循环的边界条件相同,都采用遍历第一个点不遍历到最后一个点,也就是左闭右开,所以需要设置一个防止遍历到最后点的条件,offset = 1
,如何防止到遍历到最后一个点,那么就只需要 n-offset
即可。由于 n
可能为奇数,中心点的填充也需要考虑,只需要设置中心点元素等于最后的 count
即可,中心点为 mid,mid = Math. floor (n/2)
,最关键的还是每次循环的切换,第一次遍历相当于是列遍历,也就是 j =startY
开始,直到 n - offset
结束,第二次遍历则是相当于行遍历,也就是 i = startX
开始,直到 n - offset
结束,第三次遍历接着之前的 j
,继续往回遍历,也就是到初始的 startY
结束,第四次遍历则是接着之前的 i
,往回遍历,最后到 startX
结束,接着就进入到第二圈,所有的位置都需要更新,startX,startY ,offset
。
var generateMatrix = function(n) {
let startX = 0 ,startY = 0
let offSet = 1
let count = 1
let nums = new Array(n).fill(0).map(() => new Array(n).fill(0));
let loop = Math.floor(n/2)
let mid = Math.floor(n/2)
while(loop--){
for(j = startY;j<n-offSet;j++){
nums[startX][j] =count++
}
for(i =startX;i<n -offSet;i++){
nums[i][j] = count++
}
for(;j>startY;j--){
nums[i][j] =count++
}
for(;i>startX;i--){
nums[i][j] =count++
}
startX++
startY++
offSet++
}
if(n%2===1){
nums[mid][mid]=count
}
return nums
};
209. 长度最小的子数组
题目:
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的子数组[numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
示例 1:
输入: target = 7, nums = [2,3,1,2,4,3]
输出: 2
示例 2:
输入: target = 4, nums = [1,4,4]
输出: 1
示例 3:
输入: target = 11, nums = [1,1,1,1,1,1,1,1]
输出: 0
思路:
还是通过双指针的方法进行查询,首先两个指针 i, j
,让一个指针 i
,在原地保持不动,另外一个指针 j
不断往后移动,并定义一个 sum,把每次移动的值包括初始值加上,接着根据 sum
和 target
大小的对比,判断指针 i
是否要向前移动,如果指针 i
要向前移动,需要把 sum
中存的 nums[i]
的数值删除,然后进行一次最小区间的比较,看是否满足条件,并且 i++
。
var minSubArrayLen = function(target, nums) {
let i = 0
let result = Infinity
let sum = 0
for(let j = 0;j <= nums.length;j++){
sum+=nums[j]
while(sum >= target){
sum -= nums[i]
result = Math.min(result,j - i +1)
i++
}
}
return result === Infinity?0:result
};
58. 区间和
题目:
给定一个整数数组 Array,请计算该数组在每个指定区间内元素的总和。
输入:
第一行输入为整数数组 Array 的长度 n,接下来 n 行,每行一个整数,表示数组的元素。随后的输入为需要计算总和的区间下标:a,b (b > = a),直至文件结束。
输出:
输出每个指定区间内元素的总和。
思路:
通过构建前缀和矩阵进行计算,假设有一个矩阵 arr=[1,2,3,4,5,6,7,8,9]
,将他的元素依次累加形成新的矩阵 sum = [1,3,6,10,15,21,28,36,45]
,此时,sum 中每一项对应的是,sum = [arr[0],arr[0+1], arr[0+1+2], arr[0+1+2+3],.....]
,如果要计算 arr
矩阵的在 0-1
之间的区间和,只需要考虑 sum
索引对应右边边界的值 sum[1]
,其他同理。如果要计算 arr
矩阵的在 1-2
之间的区间和,需要将 sum[2] - sum[0]
,对应 arr[0+1+2] - arr[0]
。
ACM 编码 JS Node 对应两种不同的 JS 模板
未超时版本
const rl = require ("readline"). createInterface ({ input: process. stdin });
let inputLines = [];
rl.on ('line', (line) => {
inputLines.push (line.trim ());
});
rl.on ('close', () => {
const n = parseInt(inputLines[0]);
let sum = new Array (n);
sum[0] = parseInt(inputLines[1]);
for (let i = 1; i < n; i++) {
let count = parseInt(inputLines[i + 1]);
sum[i] = sum[i - 1] + count;
}
for (let i = n + 1; i < inputLines.length; i++) {
let [a, b] = inputLines[i].split(' ').map(Number);
console.log(a === 0 ? sum[b] : sum[b] - sum[a - 1]);
}
});
超时版本
const rl = require("readline").createInterface({ input: process.stdin });
const iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function () {
let inputLines = []
while(line = await readline()){
inputLines.push(line.trim());
}
const n = parseInt(inputLines[0]);
let sum = new Array(n)
sum[0] = parseInt(inputLines[1])
for(let i =1;i<n;i++){
let count = parseInt(inputLines[i+1])
sum[i] = sum[i-1] + count
}
for(i = n + 1;i<inputLines.length;i++){
let [a,b] = inputLines[i].split(' ').map(Number)
if(a===0){
console.log(sum[b])
}else{
console.log(sum[b]-sum[a-1])
}
}
}();