区間の数え上げ《しゃくとり法》

累積和メニュー【区間の数え上げ 1 〜 4】

【区間の数え上げ 1】コード

// しゃくとり法(Two Pointer Approach)
// result = 出力値, sum = 区間の総和, right = 区間の右端, N = 数列の要素数, K = 境界値
const TPA = (result, sum, right, N, K) => {
   for (let left = 0; left < N; left++) {  // 区間の左端
      while (right < N && sum + A[right] <= K) {  // rightN 未満で sumK 以下の間…
         sum += A[right];  // sumA[right] を加算
         right++;  // 右端を1つ進める
      }
      result += right - left;  // 右端のindex - 左端のindex
      if (right === left) {  // 右端 と 左端 が同じなら
         right++;  // 右端を1つ進める
      } else {
         sum -= A[left];  // 総和 から 左端の値 を減算
      }
   }
   return result;
};
const A = [1, 5, 9, 1, 20, 5, 3, 6, 5, 4];
console.log(TPA(0, 0, 0, 10, 15));
hogeちゃんの画像

問題文の解説 を参照しながら実装しました。

【区間の数え上げ 2】コード

reader.on('close', () => {
// しゃくとり法(Two Pointer Approach)
// result = 出力値, sum = 区間の総和, right = 区間の右端, N = 数列の要素数, K = 境界値
   const TPA = (result, sum, right, N, K) => {
      for (let left = 0; left < N; left++) {  // 区間の左端
         while (right < N && sum + A[right] <= K) {  // rightN 未満で sumK 以下なら…
            sum += A[right];  // sumA[right] を加算
            right++;  // 右端を1つ進める
         }
         result += right - left;  // 右端のindex - 左端のindex
         if (right === left) {  // 右端 と 左端 が同じなら
            right++;  // 右端を1つ進める
         } else {
            sum -= A[left];  // 総和 から 左端の値 を減算
         }
      }
      return result;
   };
   const A = lines[0].split(' ').map(Number);
   console.log(TPA(0, 0, 0, 10, 15));
});
hogeちゃんの画像

配列 A の値を 標準入力から受け取っています。それ以外は【STEP: 1】と同じです。

【区間の数え上げ 3】コード

reader.on('close', () => {
// しゃくとり法(Two Pointer Approach)
// result = 出力値, sum = 区間の総和, right = 区間の右端, N = 数列の要素数, K = 境界値
   const TPA = (result, sum, right, N, K) => {
      for (let left = 0; left < N; left++) {  // 区間の左端のindex
         while (right < N && sum + A[right] <= K) {  // rightN 未満で sumK 以下なら…
            sum += A[right];  // sumA[right] を加算
            right++;  // 右端を1つ進める
         }
         result += right - left;  // 右端のindex - 左端のindex
         if (right === left) {  // 右端 と 左端 が同じなら
            right++;  // 右端を1つ進める
         } else {
            sum -= A[left];  // 総和 から 左端の値 を減算
         }
      }
      return result;
   };
   const k = Number(lines[0]);
   const A = lines[1].split(' ').map(Number);
   console.log(TPA(0, 0, 0, 10, k));
});
hogeちゃんの画像

求める区間の総和が 15以下 から k 以下 になりました。それ以外は【STEP: 2】と同じです。

【区間の数え上げ 4】コード

reader.on('close', () => {
// しゃくとり法(Two Pointer Approach)
// result = 出力値, sum = 区間の総和, right = 区間の右端, N = 数列の要素数, K = 境界値
   const TPA = (result, sum, right, N, K) => {
      for (let left = 0; left < N; left++) {  // 区間の左端のindex
         while (right < N && sum + A[right] <= K) {  // rightN 未満で sumK 以下なら…
            sum += A[right];  // sumA[right] を加算
            right++;  // 右端を1つ進める
         }
         result += right - left;  // 右端のindex - 左端のindex
         if (right === left) {  // 右端 と 左端 が同じなら
            right++;  // 右端を1つ進める
         } else {
            sum -= A[left];  // 総和 から 左端の値 を減算
         }
      }
      return result;
   };
   const [n, k] = lines[0].split(' ').map(Number);
   const A = lines[1].split(' ').map(Number);
   console.log(TPA(0, 0, 0, n, k));
});
hogeちゃんの画像

与えられる a の要素数が 10個 から n 個になりました。それ以外は【STEP: 3】と同じです。

コメント