diff --git a/README.md b/README.md index 5c0d42a7..cd09e8a0 100644 --- a/README.md +++ b/README.md @@ -599,3 +599,4 @@ Profile on LeetCode: [fartem](https://leetcode.com/fartem/). | 621. Task Scheduler | [Link](https://leetcode.com/problems/task-scheduler/) | [Link](./lib/medium/621_task_scheduler.rb) | [Link](./test/medium/test_621_task_scheduler.rb) | | 622. Design Circular Queue | [Link](https://leetcode.com/problems/design-circular-queue/) | [Link](./lib/medium/622_design_circular_queue.rb) | [Link](./test/medium/test_622_design_circular_queue.rb) | | 623. Add One Row to Tree | [Link](https://leetcode.com/problems/add-one-row-to-tree/) | [Link](./lib/medium/623_add_one_row_to_tree.rb) | [Link](./test/medium/test_623_add_one_row_to_tree.rb) | +| 641. Design Circular Deque | [Link](https://leetcode.com/problems/design-circular-deque/) | [Link](./lib/medium/641_design_circular_deque.rb) | [Link](./test/medium/test_641_design_circular_deque.rb) | diff --git a/leetcode-ruby.gemspec b/leetcode-ruby.gemspec index 9dbcc97c..ea9344e0 100644 --- a/leetcode-ruby.gemspec +++ b/leetcode-ruby.gemspec @@ -5,7 +5,7 @@ require 'English' ::Gem::Specification.new do |s| s.required_ruby_version = '>= 3.0' s.name = 'leetcode-ruby' - s.version = '7.3.4' + s.version = '7.3.5' s.license = 'MIT' s.files = ::Dir['lib/**/*.rb'] + %w[README.md] s.executable = 'leetcode-ruby' diff --git a/lib/medium/641_design_circular_deque.rb b/lib/medium/641_design_circular_deque.rb new file mode 100644 index 00000000..94e4fdc0 --- /dev/null +++ b/lib/medium/641_design_circular_deque.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +require_relative '../common/linked_list' + +# https://leetcode.com/problems/design-circular-deque/description/ +class MyCircularDeque + # @param {Integer} k + def initialize(k) + @size = k + @actual_size = 0 + @head = ::ListNode.new(0) + @tail = nil + end + + # @param {Integer} value + # @return {Boolean} + def insert_front(value) + return false if is_full + + new_head = ::ListNode.new(value) + if @tail + new_head.next = @head.next + @head.next = new_head + else + @tail = new_head + @head.next = @tail + @tail.next = @head + end + + @actual_size += 1 + + true + end + + # @param {Integer} value + # @return {Boolean} + def insert_last(value) + return false if is_full + + new_tail = ::ListNode.new(value) + if @tail + @tail.next = new_tail + else + @head.next = new_tail + end + + @tail = new_tail + @actual_size += 1 + + true + end + + # @param {Boolean} + def delete_front + return false if @actual_size.zero? + + @head.next = @head.next.next + @tail = nil if @actual_size == 1 + + @actual_size -= 1 + + true + end + + # @param {Boolean} + def delete_last + return false if @actual_size.zero? + + if @actual_size == 1 + @head.next = nil + @tail = nil + else + new_tail = @head.next + new_tail = new_tail.next until new_tail.next == @tail + new_tail.next = @head + @tail = new_tail + end + + @actual_size -= 1 + + true + end + + # @return {Integer} + def get_front = @actual_size.zero? ? -1 : @head.next.val + + # @return {Integer} + def get_rear = @actual_size.zero? ? -1 : @tail.val + + # @return {Boolean} + def is_empty = @actual_size.zero? + + # @return {Boolean} + def is_full = @actual_size == @size +end diff --git a/test/medium/test_641_design_circular_deque.rb b/test/medium/test_641_design_circular_deque.rb new file mode 100644 index 00000000..c4a41927 --- /dev/null +++ b/test/medium/test_641_design_circular_deque.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require_relative '../test_helper' +require_relative '../../lib/medium/641_design_circular_deque' +require 'minitest/autorun' + +class DesignCircularDequeTest < ::Minitest::Test + def test_default_one + my_circular_deque = ::MyCircularDeque.new(3) + + assert(my_circular_deque.insert_last(1)) + assert(my_circular_deque.insert_last(2)) + assert(my_circular_deque.insert_front(3)) + assert(!my_circular_deque.insert_front(4)) + + assert_equal(2, my_circular_deque.get_rear) + + assert(my_circular_deque.is_full) + assert(my_circular_deque.delete_last) + assert(my_circular_deque.insert_front(4)) + + assert_equal(4, my_circular_deque.get_front) + end + + def test_additional_one + my_circular_deque = ::MyCircularDeque.new(5) + + assert(my_circular_deque.insert_front(7)) + assert(my_circular_deque.insert_last(0)) + + assert_equal(7, my_circular_deque.get_front) + + assert(my_circular_deque.insert_last(3)) + assert_equal(3, my_circular_deque.get_rear) + + assert(my_circular_deque.insert_front(9)) + + assert_equal(3, my_circular_deque.get_rear) + assert_equal(9, my_circular_deque.get_front) + assert_equal(9, my_circular_deque.get_front) + + assert(my_circular_deque.delete_last) + + assert_equal(0, my_circular_deque.get_rear) + + assert(my_circular_deque.delete_last) + assert(my_circular_deque.delete_last) + + assert(my_circular_deque.insert_front(9)) + assert(my_circular_deque.delete_front) + assert(my_circular_deque.delete_last) + end +end