thảo luận [Học Tập] Topic thuật toán

  • Người tạo chủ đề Người tạo chủ đề unknowpc90
  • Ngày bắt đầu Ngày bắt đầu
Nghĩ cách giải khi được dùng thêm O(N) bộ nhớ sau đó cải tiến bằng cách dùng trực tiếp trên input thay vì phải tạo thêm bộ nhớ
 
Nay vừa vào làm thử 1 bài LeetCode, đề cũng đơn giản nhưng có giới hạn bộ nhớ nên cũng khá khoai. Các bác hứng thú có thể vào thảo luận cho vui :D

Vì cái đề đòi O(1) space nên có 2 khả năng:
  • Hoặc là dùng lượng bộ nhớ fixed. Vd: constraint là 5*10^5 thì cấp phát luôn vector<int> 500k phần tử.
  • Hoặc là sử dụng lại cái mảng input

Nhận thấy giả sử cái mảng có n phần tử, thì:
1. Hoặc là nó thiếu một số nào đó trong khoảng từ 1 - n
2. Nếu không thì nghĩa là mảng đó là một hoán vị của mảng 1...n => số bị thiếu là số n + 1

Nhưng theo constraint thì n <= 500000, nên có thể làm ý tưởng đơn giản (nhưng k tối ưu). Là dùng luôn 1 cái bitset<500000>. Lặp qua từng phần tử, nếu nó nằm trong khoảng 1 => 500000 thì bật bit tương ứng lên, k thì bỏ qua.

Sau đó duyệt lại i từ 1 => 500000. Xem số nào thiếu thì return. Nếu k có số nào thiếu thì return về 500001.

p/s: Ý tưởng trên cũng có thể dùng cho pp2 là dùng lại luôn cái mảng hiện tại, thay vì bitset. Nhưng lười suy diễn thêm quá :D:D
 
Bài này t từng làm rồi. Có một nhận xét là kết quả cần tìm sẽ luôn nằm trong khoảng từ [1,nums.size()]. :big_smile:
 
Do kết quả sẽ chỉ nằm trong khoảng từ [1,nums.size()+1] nên ý tưởng là sẽ dùng lại luôn cái nums để check.
C++:
class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        for (int i = 0; i < nums.size(); ++i) {
            while (nums[i] != i+1 && nums[i] <= nums.size() && nums[i] > 0 && nums[i] != nums[nums[i]-1]) swap(nums[i], nums[nums[i]-1]);
        }
     
        int i;
        for (i = 0; i < nums.size() && nums[i] == i+1; ++i);
        return i+1;
    }
};

Việc swap nhằm đưa các số về đúng vị trí, do đó chỉ có n lần swap. Nên độ phức tạp chỉ là O(n).
 
Cách của bác @_Gia_Cat_Luong_ là O(N) bộ nhớ rồi mà nhỉ. Mình nghĩ cách của bác @thuyduong2007 mới là cách chuẩn. Cơ mà đoạn xử lý swap đấy cũng không phải đơn giản.

Mình thấy mấy bài interview hay có cái trò bắt phải sử dụng lại bộ nhớ trong input để làm những thứ khác. Mình khá anti với những bài thế này vì nó là một practice cực kì tệ khi code. Nguyên tắc vẫn nên là mỗi biến phải dùng cho một mục đích riêng chứ không nên dùng lẫn vào nhau như thế.
 
Cách của bác @_Gia_Cat_Luong_ là O(N) bộ nhớ rồi mà nhỉ. Mình nghĩ cách của bác @thuyduong2007 mới là cách chuẩn. Cơ mà đoạn xử lý swap đấy cũng không phải đơn giản.

Mình thấy mấy bài interview hay có cái trò bắt phải sử dụng lại bộ nhớ trong input để làm những thứ khác. Mình khá anti với những bài thế này vì nó là một practice cực kì tệ khi code. Nguyên tắc vẫn nên là mỗi biến phải dùng cho một mục đích riêng chứ không nên dùng lẫn vào nhau như thế.
fixed mem thì là O(1) chứ fen =)). Cách của mình dĩ nhiên là cheaty, nhưng nếu đánh giá đúng lý thuyết thì vẫn là O(1) :v.
 
Cách của bác @_Gia_Cat_Luong_ là O(N) bộ nhớ rồi mà nhỉ. Mình nghĩ cách của bác @thuyduong2007 mới là cách chuẩn. Cơ mà đoạn xử lý swap đấy cũng không phải đơn giản.

Mình thấy mấy bài interview hay có cái trò bắt phải sử dụng lại bộ nhớ trong input để làm những thứ khác. Mình khá anti với những bài thế này vì nó là một practice cực kì tệ khi code. Nguyên tắc vẫn nên là mỗi biến phải dùng cho một mục đích riêng chứ không nên dùng lẫn vào nhau như thế.
Ko đồng ý nhé, ví dụ Arrays.sort(int[]), hoặc builder pattern.
 
Ko đồng ý nhé, ví dụ Arrays.sort(int[]), hoặc builder pattern.
Bác có thể giải thích thêm về Arrays.sort được không? Bác sort lại mảng thì ý nghĩa của mảng vẫn là chứa các dữ liệu, chỉ thay đổi vị trí các phần tử. Còn trong bài kia thì dùng mảng input như mảng đánh dấu là thay đổi hoàn toàn ý nghĩa của mảng rồi.
 

Thống kê chủ đề

Ngày tạo
unknowpc90,
Người trả lời cuối
Spaghetti Code,
Trả lời
1.460
Lượt xem
154.127
Quay lại
Lên đầu trang