thảo luận Leetcode mỗi ngày

Bài này tự chế được hướng giả nên không quay cóp. Tự chế:

- Một mảng đẹp thì nó có k phần tử lẻ, vd k = 2: [2, 2, 2, 1, 2, 1, 2, 2, 2]
Thì nó sẽ có 16 trường hợp:
[1, 2, 1], [2, 1, 2, 1, 2]...

Công thức: (Số phần tử chẵn bên trái + 1) * (Số phần tử chẵn bên phải + 1) = (3 + 1) * (3 + 1) = 16.
Mình start biến đếm từ 1 luôn để đỡ cộng 1.



Lúc đầu mình chỉ xài biến để lưu left, right, nhưng trường hợp mấy số chẵn len giữa số lẻ thì nảy sinh ra nhu cầu cần xài mảng để lưu lại số lượng số chẵn.

Bây giờ hình dung ta có mảng đếm số lượng số chẵn kẹp giữa số lẻ, start biến đếm là 1. Theo như vd trên:
[2, 2, 2, 1, 2, 1, 2, 2, 2] => evens = [4, 2, 4]

Hình dung có 1 số lẻ kẹp giữa 2 phần tử mảng even trên. 4 (1) 2 (1) 4. Để ra kết quả: Khi số lượng của mảng count even đã > k (lúc này có k số lẻ kẹp giữa). Lấy left = đầu mảng, right = cuối mảng.
Nhân left với right, đưa vào result.

Swift:
result += left * right
//4 * 4 = 16

Nhớ bỏ phần tử đầu tiên của mảng even vì nó đã hết tác dụng.

Sau cùng, duyệt xong mảng nums thì gọi một lần nữa ở bên ngoài. Trong trường hợp mảng kết thúc bằng số chẵn và số lượng số lẻ đã đạt k.



Swift:
class Solution {
    func numberOfSubarrays(_ nums: [Int], _ k: Int) -> Int {
        var result = 0

        var countOdd = 0
        var storeListEvens:[Int] = []
        var storeEven = 1
        for (index, value) in nums.enumerated() {
            if value%2 == 1 {
                countOdd += 1
               // Add storeEven in to list & reset counter
                storeListEvens.append(storeEven)
                storeEven = 1

               // Now we have enough k odds.
                if storeListEvens.count > k {
                    let left = storeListEvens.first!
                    let right = storeListEvens.last!
                    storeListEvens.removeFirst()
                    result += left * right
                    countOdd -= 1
                }
            } else {
                storeEven += 1
            }
        }

        if storeListEvens.count == k {
            let left = storeListEvens.first!
            let right = storeEven // List nums doesn't end by an odd, so the even count remain here.
            result += left * right
        }

        return result
    }
}
 
Last edited:
C-like:
impl Solution {
    pub fn number_of_subarrays(nums: Vec<i32>, k: i32) -> i32 {
        let idx: Vec<_> = nums
            .iter()
            .enumerate()
            .filter_map(|(i, n)| (n % 2 != 0).then_some(i))
            .collect();

        let k = if k as usize > idx.len() {
            return 0;
        } else {
            k as usize
        };

        let lasti = idx.len() - k;
        return (0..=lasti).fold(0, |acc, i| {
            let l = if i == 0 {
                idx[i] + 1
            } else {
                idx[i] - idx[i - 1]
            };
            let h = if i < lasti { idx[i + k] } else { nums.len() } - idx[i + k - 1];
            acc + l * h
        }) as i32;
    }
 
Python:
class Solution:
    def numberOfSubarrays(self, nums: List[int], k: int) -> int:
        map = {0: 1}
        sum = 0
        ans = 0
        for n in nums:
            sum += n % 2
            if map.get(sum - k):
                ans += map[sum-k]
            if map.get(sum):
                map[sum] += 1
            else:
                map[sum] = 1
        return ans

Đọc giải thấy cách hashing này hay quá
 
Java:
fun numberOfSubarrays(nums: IntArray, k: Int): Int {
        var oddCount = 0
        var prevIndex = 0
        var numSubarrayEndAtI = 0
        var total = 0
        for (num in nums) {
            if (num and 1 == 1) {
                oddCount++
                numSubarrayEndAtI = 0
            }
            while (oddCount == k) {
                oddCount -= nums[prevIndex++] and 1
                numSubarrayEndAtI++
            }
            total += numSubarrayEndAtI
        }
        return total
    }
 
Dạo này bị không còn cảm giác hưng phấn tột độ khi tự giải được medium nữa rồi :(
Java:
class Solution {
    public int numberOfSubarrays(int[] nums, int k) {
        int n = nums.length;

        for (int i = 0; i < n; i++) {
            nums[i] = nums[i] % 2 == 0 ? 0 : 1;
        }

        Map<Integer, Integer> map = new HashMap<>();
        int curSum = 0;
        int ans = 0;

        for (int i = 0; i < n; i++) {
            map.put(curSum, map.getOrDefault(curSum, 0) + 1);
            curSum += nums[i];

            ans += map.getOrDefault(curSum - k, 0);
        }

        return ans;
    }
}
 
Thứ 7 nhẹ nhàng
Java:
object Solution {
  def numberOfSubarrays(nums: Array[Int], k: Int): Int = {
    val n = nums.length
    val transformedNums = nums.map(num => if (num % 2 == 0) 0 else 1)

    val prefixSumCount = scala.collection.mutable.Map[Int, Int]().withDefaultValue(0)
    var curSum = 0
    var ans = 0

    transformedNums.indices.foreach { i =>
      prefixSumCount(curSum) += 1
      curSum += transformedNums(i)
      ans += prefixSumCount(curSum - k)
    }

    ans
  }
}
 
Dạo này bị không còn cảm giác hưng phấn tột độ khi tự giải được medium nữa rồi :(
Java:
class Solution {
    public int numberOfSubarrays(int[] nums, int k) {
        int n = nums.length;

        for (int i = 0; i < n; i++) {
            nums[i] = nums[i] % 2 == 0 ? 0 : 1;
        }

        Map<Integer, Integer> map = new HashMap<>();
        int curSum = 0;
        int ans = 0;

        for (int i = 0; i < n; i++) {
            map.put(curSum, map.getOrDefault(curSum, 0) + 1);
            curSum += nums[i];

            ans += map.getOrDefault(curSum - k, 0);
        }

        return ans;
    }
}
Cái này giống như chơi đồ ấy, khi nhờn rồi thì phải lên đô mới thấy phê đc, :big_smile:
 
Bài hôm nay em phải quay lại làm
mới hiểu rồi làm được =((=((
C++:
class Solution {
public:
    int numberOfSubarrays(vector<int>& nums, int k) {
        vector<int> v;
        for(int num : nums){
            if(num % 2 == 1){
                v.emplace_back(1);
            }
            else{
                v.emplace_back(0);
            }
        }
        int preSum {0};
        int count {0};
        unordered_map<int,int> mpp;
        mpp[0] = 1;
        for(int i = 0; i < v.size(); i++){
            preSum += v[i];
            count += mpp[preSum - k];
            mpp[preSum]++;
        }

        return count;
    }
};
 
C-like:
impl Solution {
    pub fn number_of_subarrays(nums: Vec<i32>, k: i32) -> i32 {
        let k = k as usize;
        let (mut ps, mut pacc) = (vec![0; nums.len() + 1], 0usize);
        ps[0] = 1;

        return (0..nums.len()).fold(0, |sacc, i| {
            pacc += (nums[i] % 2) as usize;
            ps[pacc] += 1;

            if pacc >= k && ps[pacc - k] != 0 {
                sacc + ps[pacc - k]
            } else {
                sacc
            }
        });
    }
}
 
Java:
    public static int numberOfSubarrays(int[] nums, int k) {
        int count,res;
        int i;
        int first = curr = 0;
        int iRight = 1;
        int curr = 0;
        curLeft = curRight =count = res= 0;
        int[] left = new int[nums.length+1];
        int[] right = new int[nums.length+1];
        for(i=0; i<nums.length;i++){
            if(nums[i]%2==1){
                count++;
                if(count == 1)
                    first = i;
                left[count] = i-curr;
                curr = i;
            }
            if(count==k) {
                break;
            }
        }
        if(first ==0) left[1] = 1;
        else left[1]++;
        if(count!=k) return 0;
        i++;
        Arrays.fill(right, 1);
        for(int j =i; j<nums.length;j++){
            if(nums[j]%2==0) right[iRight]++;
            else {
                res+= left[iRight]*right[iRight];
                left[k+iRight]=right[iRight];
                iRight++;
            }
          }
        res+= left[iRight]*right[iRight];
        return res;
}
Nhận ra dùng array code hơi nhọc tí nhưng chạy phải nhanh gấp đôi so với hashmap :adore:
 
Last edited:
Java:
    public static int numberOfSubarrays(int[] nums, int k) {
        int count,res;
        int i;
        int first = curr = 0;
        int iRight = 1;
        int curr = 0;
        curLeft = curRight =count = res= 0;
        int[] left = new int[nums.length+1];
        int[] right = new int[nums.length+1];
        for(i=0; i<nums.length;i++){
            if(nums[i]%2==1){
                count++;
                if(count == 1)
                    first = i;
                left[count] = i-curr;
                curr = i;
            }
            if(count==k) {
                break;
            }
        }
        if(first ==0) left[1] = 1;
        else left[1]++;
        if(count!=k) return 0;
        i++;
        Arrays.fill(right, 1);
        for(int j =i; j<nums.length;j++){
            if(nums[j]%2==0) right[iRight]++;
            else {
                res+= left[iRight]*right[iRight];
                left[k+iRight]=right[iRight];
                iRight++;
            }
          }
        res+= left[iRight]*right[iRight];
        return res;
}
Nhận ra dùng array code hơi nhọc tí nhưng chạy phải nhanh gấp đôi so với hashmap :adore:
Hashmap bản chất vẫn là array thôi mà fen
 
Hashmap bản chất vẫn là array thôi mà fen
2 thằng này có giống nhau tí nào đâu mà chung bản chất vậy fence
YGfWNig.gif
bZut9mH.gif
 
À lại nhắc tới vụ array với hashmap, anh em lội lại thớt để xem các chiên da seminar nhé
KgmQHtR.png

Lâu ko động lý thuyết, nhìn mấy thuật ngữ open addressing với seperate chaining đúng như chó xem bản đồ
4gmOAMB.png

 
Last edited:
Back
Top