---
# System prepended metadata

title: 523. Continuous Subarray Sum

---

Daily 08/06/2024: [523. Continuous Subarray Sum](https://leetcode.com/problems/continuous-subarray-sum/)

# 1. Tóm tắt đề bài

- Cho một mảng số nguyên ```nums``` và một số nguyên ```k```, trả về ```true``` nếu ```nums``` có **mảng con tốt** hoặc ```false``` nếu ngược lại .
- **Một mảng con tốt** là một mảng con trong đó:
    - Chiều dài của nó ít nhất là 2 , và
    - Tổng các phần tử của mảng con là bội số của k.
- **Lưu ý** rằng:
    - Mảng con là phần liền kề của mảng.
    - Một số nguyên ```x``` là bội số của ```k``` nếu tồn tại một số nguyên ```n``` sao cho ```x = n * k```. ```0``` luôn là bội số của ```k```.

#### Giới hạn
- $1 \le$ ```nums.length``` $\le 10^5$
- $1 \le$ ```nums[i]``` $\le 10^9$
- $0 \le$ ```sum(nums[i])``` $\le 2^{31} - 1$
- $1 \le$ ```k``` $\le 2^{31} - 1$

# 2. Tóm tắt lời giải
#### Phân tích
- Với hướng tiếp cận đầu tiên là chạy trâu thì chúng ta đơn giản là xét hết các khoảng xong tính tổng từng khoảng. Độ phức tạp là $O(n^3)$.
- Cải tiến khi chúng ta dùng prefix sum thì sẽ cải tiến xuống $O(n^2)$. Với những bạn mới thì có thể tham khảo ở đây [https://wiki.vnoi.info/algo/data-structures/prefix-sum-and-difference-array.md].
- Tiếp đến thì chúng ta sẽ phân tích là tổng chia hết cho ```k```. Thế thì chúng chỉ quan tâm tới số dư của nó chia ```k``` bằng 0 là được. Vậy thì ý tưởng cải tiến đơn giản hơn là kiểm tra số dư đó đã xuất hiện trong ```prefix sum``` chưa. Giả sử có ```prefix[l -  1]``` và ```prefix[r]``` cùng số dư thì theo tính chất cơ bản ```prefix[r] - prefix[l - 1]``` sẽ chia hết cho ```k```. Hay tổng các phần tử thừ l tới ```r``` sẽ chia hết cho ```k``` và trả về ```true```.
# 3. Lời giải chi tiết
#### Thuật toán
 - Sử dụng Hash Table tùy theo ngôn ngữ bạn đọc sử dụng.
#### Code
```C#
public class Solution {
    public bool CheckSubarraySum(int[] nums, int k) {
        int prevSum = nums[0] % k;
        int currSum = 0;
        HashSet<int> prefixSum = new HashSet<int>();

        for (int i = 1; i < nums.Length; i++)
        {
            currSum = (prevSum + nums[i]) % k;
            
            if(currSum % k == 0 || prefixSum.Contains(currSum))
                return true;

            if(!prefixSum.Contains(prevSum))
                prefixSum.Add(prevSum);
                
            prevSum = currSum;
        }
        return false;
    }
}

```
#### Độ phức tạp
$O(n)$.
# 4. Kết luận & gợi ý mở rộng
- Một bài cuối tuần khá nhẹ nhàng.

> Hãy dùng nghị lực và sự kiên trì để đánh bại mọi thứ.

###### #Hashtag: <span style='color: blue'>Brute Force, Hash Table</span>
