- vừa được xem lúc

HashMap cùng 2 bài toán Roman và vòng lặp linked list

0 0 1

Người đăng: Minhion

Theo Viblo Asia

Hi mọi người, hôm nay mình sẽ giới thiệu 2 bài toán sử dụng HashMap thuộc vào nhóm easy.

Bài toán

Roman to Int

Các số La Mã được biểu diễn bằng bảy ký hiệu khác nhau: I, V, X, L, C, D và M. Ký hiệu Giá trị I 1 V 5 X 10 L 50 C 100 D 500 M 1000 Ví dụ:

Số 2 được viết là II trong số La Mã, nghĩa là hai số 1 cộng lại với nhau. Số 12 được viết là XII, tức là X + II. Số 27 được viết là XXVII, tức là XX + V + II. Các số La Mã thường được viết từ lớn nhất đến nhỏ nhất từ trái sang phải. Tuy nhiên, số 4 không được viết là IIII mà viết là IV. Vì số 1 (I) đứng trước số 5 (V) nên ta thực hiện phép trừ, dẫn đến kết quả là 4. Nguyên tắc này cũng áp dụng cho số 9, được viết là IX. Có sáu trường hợp sử dụng phép trừ trong số La Mã:

I có thể đứng trước V (5) và X (10) để tạo thành 4 và 9. X có thể đứng trước L (50) và C (100) để tạo thành 40 và 90. C có thể đứng trước D (500) và M (1000) để tạo thành 400 và 900.

Hướng tiếp cận

Nhìn sơ qua bài toán ta có thể thấy muốn tính giá trị các số la mã ta cộng tổng các chữ số từ trái sang phải và đồng thời gộp chung trường hợp đặc biệt IV, IX, XL , XC, CD, CM để tính cặp riêng ( các trường hợp này có điểm chung là chữ số đầu tiên nhỏ hơn chữ số đằng sau nó). Vì vậy chúng ta có thể giải bài toán như sau, mình xin phép trình bày bài giải bằng python nhé:

time complexity: O(n) - n is length of s

space complexity: O(1)

class Solution: def romanToInt(self, s:str) -> int: if len(s) == 0: return 0 roman_dict = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000} sum = roman_dict[s[0]] for i in range(1, len(s)): if roman_dict[s[i-1]] < roman_dict[s[i]]: sum += roman_dict[s[i]] - 2 * roman_dict[s[i-1]] else: sum += roman_dict[s[i]] return sum solution = Solution()
print(solution.romanToInt("III")) # 3
print(solution.romanToInt('IV')) # 4
print(solution.romanToInt('XVI')) # 16
print(solution.romanToInt('MCMXCIV')) # 1000 + 900 + 40 + 4 

Vòng lặp Linked list

Cho 1 head, đầu của một danh sách liên kết (ListNode), hãy xác định xem danh sách liên kết đó có vòng lặp hay không.

Một danh sách liên kết có vòng lặp nếu có một nút trong danh sách có thể được truy cập lại bằng cách liên tục theo con trỏ next. Trong đó, pos được sử dụng để biểu thị chỉ số của nút mà con trỏ next của nút cuối cùng (tail) trỏ tới. Lưu ý rằng pos không được truyền dưới dạng tham số.

Trả về true nếu danh sách liên kết có vòng lặp. Nếu không có vòng lặp, trả về false.

class ListNode: def init(self, x): self.val = x self.next = None Ex: image.png

Hướng tiếp cận

Chúng ta sẽ sử dụng thuật toán Floyd 's Tortoise and hare cho 2 con trỏ slow và fast. Trong đó:

  • Slow: Mỗi lần chỉ được di chuyển 1 nước
  • Fast: Mỗi lần di chuyển được 2 nước

-> Theo nguyên tắc vòng lặp, đến 1 lúc nào đó 2 con trỏ sẽ phải gặp nhau.

Các bước thực hiện: Khởi tạo hai con trỏ slow và fast, cả hai đều bắt đầu từ đầu danh sách liên kết (head). Di chuyển: slow tiến một bước mỗi lần. fast tiến hai bước mỗi lần. Kiểm tra: Nếu slow và fast gặp nhau, nghĩa là có vòng lặp trong danh sách liên kết. Nếu fast hoặc fast.next là null, nghĩa là không có vòng lặp (đã tới cuối danh sách). Kết quả: Trả về true nếu có vòng lặp. Trả về false nếu không có vòng lặp.

Time complexity: O(n) - trong trường hợp tệ nhất cần loop qua toàn bộ mảng đến đến được phần tử trùng

Space complexity: O(1)


from typing import Optional class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: def hasCycle(self, head: Optional[ListNode]) -> bool: if head is None or head.next is None: return False first_node = head second_node = head.next while first_node != second_node: if second_node.next is None or second_node.next.next is None: return False first_node = first_node.next second_node = second_node.next.next return True solution = Solution()
root = ListNode(3)
root.next = ListNode(2)
root.next.next = ListNode(0)
root.next.next.next= ListNode(-4)
root.next.next.next.next = root.next
print(solution.hasCycle(root)) 

Bình luận

Bài viết tương tự

- vừa được xem lúc

Thuật toán quay lui (Backtracking)

Quay lui là một kĩ thuật thiết kế giải thuật dựa trên đệ quy. Ý tưởng của quay lui là tìm lời giải từng bước, mỗi bước chọn một trong số các lựa chọn khả dĩ và đệ quy.

0 0 51

- vừa được xem lúc

Các thuật toán cơ bản trong AI - Phân biệt Best First Search và Uniform Cost Search (UCS)

Nếu bạn từng đọc các thuật toán trong AI (Artificial Intelligence - Trí tuệ nhân tạo), rất có thể bạn từng nghe qua về các thuật toán tìm kiếm cơ bản: UCS (thuộc chiến lược tìm kiếm mù) và Best First Search (thuộc chiến lược tìm kiếm kinh nghiệm). Khác nhau rõ từ khâu phân loại rồi, thế nhưng hai th

0 0 169

- vừa được xem lúc

Sử dụng vector trong lập trình C++ - giải bài toán lập trình muôn thủa

Chào buổi tối mọi người, hôm nay lang thang trên mạng bắt gặp bài toán quen thuộc một thời của quãng đường sinh viên IT. Đấy chính là câu số 1 trong đề thi dưới đây:.

0 0 57

- vừa được xem lúc

MÔ PHỎNG THUẬT TOÁN VƯƠNG HẠO TRONG PROLOG

. 1. Các luật suy diễn trong thuật toán Vương Hạo. Luật 1: Chuyển vế các giả thuyết và kết luận ở dạng phủ định. Ví dụ: p v q, !(r ^ s), !q, p v r -> s, !p <=> p v q, p v r, p -> s, r ^ s, q.

0 0 90

- vừa được xem lúc

A* Search Algorithm

What is A* Search Algorithm. How it works. . Explanation.

0 0 58

- vừa được xem lúc

Python: Jump Search

Search là một từ khóa khá là quen thuộc đối với chúng ta. Hiểu theo đúng nghĩa đen của nó chính là "Tìm kiếm".

0 0 50