From 15c58e1aef81b9c1da44ffedb9c07fd5b894c818 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sat, 24 Feb 2024 06:56:37 +0200 Subject: [PATCH] Improved tasks 1-101 --- README.md | 310 +++++++++--------- .../java/g0001_0100/s0001_two_sum/readme.md | 80 +++-- .../s0002_add_two_numbers/readme.md | 125 ++++--- .../readme.md | 83 +++-- .../readme.md | 94 +++--- .../readme.md | 97 +++--- .../s0006_zigzag_conversion/readme.md | 79 +++-- .../s0007_reverse_integer/readme.md | 63 +++- .../s0008_string_to_integer_atoi/readme.md | 95 ++++-- .../s0009_palindrome_number/readme.md | 59 +++- .../readme.md | 80 +++-- .../s0011_container_with_most_water/readme.md | 52 ++- src/main/java/g0001_0100/s0015_3sum/readme.md | 108 +++--- .../readme.md | 95 +++--- .../readme.md | 126 ++++--- .../s0020_valid_parentheses/readme.md | 70 ++-- .../s0021_merge_two_sorted_lists/readme.md | 95 +++--- .../s0022_generate_parentheses/readme.md | 64 ++-- .../s0023_merge_k_sorted_lists/readme.md | 154 ++++----- .../s0024_swap_nodes_in_pairs/readme.md | 100 +++--- .../s0025_reverse_nodes_in_k_group/readme.md | 111 +++---- .../s0031_next_permutation/readme.md | 79 +++-- .../s0032_longest_valid_parentheses/readme.md | 86 ++--- .../readme.md | 73 +++-- .../readme.md | 85 +++-- .../s0035_search_insert_position/readme.md | 49 +-- .../s0039_combination_sum/readme.md | 78 ++--- .../s0041_first_missing_positive/readme.md | 67 ++-- .../s0042_trapping_rain_water/readme.md | 73 ++--- .../g0001_0100/s0045_jump_game_ii/readme.md | 53 ++- .../g0001_0100/s0046_permutations/readme.md | 70 ++-- .../g0001_0100/s0048_rotate_image/readme.md | 63 ++-- .../g0001_0100/s0049_group_anagrams/readme.md | 80 +++-- .../java/g0001_0100/s0051_n_queens/readme.md | 128 ++++---- .../s0053_maximum_subarray/readme.md | 51 ++- .../java/g0001_0100/s0055_jump_game/readme.md | 71 ++-- .../s0056_merge_intervals/readme.md | 57 ++-- .../g0001_0100/s0062_unique_paths/readme.md | 39 +-- .../s0064_minimum_path_sum/readme.md | 70 ++-- .../s0070_climbing_stairs/readme.md | 62 ++-- .../g0001_0100/s0072_edit_distance/readme.md | 79 +++-- .../s0073_set_matrix_zeroes/readme.md | 91 ++--- .../s0074_search_a_2d_matrix/readme.md | 64 ++-- .../g0001_0100/s0075_sort_colors/readme.md | 68 ++-- .../s0076_minimum_window_substring/readme.md | 102 +++--- .../java/g0001_0100/s0078_subsets/readme.md | 68 ++-- .../g0001_0100/s0079_word_search/readme.md | 94 +++--- .../readme.md | 115 ++----- .../readme.md | 88 ++--- .../readme.md | 48 ++- .../readme.md | 74 ++--- .../g0101_0200/s0101_symmetric_tree/readme.md | 69 ++-- 52 files changed, 2214 insertions(+), 2220 deletions(-) diff --git a/README.md b/README.md index 7f6ab0af..5a5f9a6f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ [![](https://img.shields.io/github/forks/javadev/LeetCode-in-Java?label=Fork%20me%20on%20GitHub%20&style=flat-square)](https://github.com/javadev/LeetCode-in-Java/fork) > ["For coding interview preparation, LeetCode is one of the best online resource providing a rich library of more than 300 real coding interview questions for you to practice from using one of the 7 supported languages - C, C++, Java, Python, C#, JavaScript, Ruby."](https://www.quora.com/How-effective-is-Leetcode-for-preparing-for-technical-interviews) -* [Binary Search II](#binary-search-ii) * [Dynamic Programming I](#dynamic-programming-i) * [Programming Skills I](#programming-skills-i) * [Programming Skills II](#programming-skills-ii) @@ -16,148 +15,7 @@ * [Algorithm I](#algorithm-i) * [Algorithm II](#algorithm-ii) * [Binary Search I](#binary-search-i) - -### Binary Search II - -#### Day 1 - -| | | | | | -|-|-|-|-|-|- -| 0209 |[Minimum Size Subarray Sum](src/main/java/g0201_0300/s0209_minimum_size_subarray_sum)| Medium | Array, Binary_Search, Prefix_Sum, Sliding_Window | 1 | 100.00 -| 0611 |[Valid Triangle Number](src/main/java/g0601_0700/s0611_valid_triangle_number)| Medium | Array, Sorting, Greedy, Binary_Search, Two_Pointers | 10 | 100.00 - -#### Day 2 - -| | | | | | -|-|-|-|-|-|- -| 0658 |[Find K Closest Elements](src/main/java/g0601_0700/s0658_find_k_closest_elements)| Medium | Array, Sorting, Binary_Search, Two_Pointers, Heap_Priority_Queue | 3 | 99.20 -| 1894 |[Find the Student that Will Replace the Chalk](src/main/java/g1801_1900/s1894_find_the_student_that_will_replace_the_chalk)| Medium | Array, Binary_Search, Simulation, Prefix_Sum | 2 | 76.67 - -#### Day 3 - -| | | | | | -|-|-|-|-|-|- -| 0300 |[Longest Increasing Subsequence](src/main/java/g0201_0300/s0300_longest_increasing_subsequence)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Dynamic_Programming, Binary_Search, Big_O_Time_O(n\*log_n)_Space_O(n) | 3 | 98.63 -| 1760 |[Minimum Limit of Balls in a Bag](src/main/java/g1701_1800/s1760_minimum_limit_of_balls_in_a_bag)| Medium | Array, Binary_Search | 44 | 78.49 - -#### Day 4 - -| | | | | | -|-|-|-|-|-|- -| 0875 |[Koko Eating Bananas](src/main/java/g0801_0900/s0875_koko_eating_bananas)| Medium | Array, Binary_Search | 15 | 91.32 -| 1552 |[Magnetic Force Between Two Balls](src/main/java/g1501_1600/s1552_magnetic_force_between_two_balls)| Medium | Array, Sorting, Binary_Search | 39 | 99.65 - -#### Day 5 - -| | | | | | -|-|-|-|-|-|- -| 0287 |[Find the Duplicate Number](src/main/java/g0201_0300/s0287_find_the_duplicate_number)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Binary_Search, Two_Pointers, Bit_Manipulation, Big_O_Time_O(n)_Space_O(n) | 2 | 99.82 -| 1283 |[Find the Smallest Divisor Given a Threshold](src/main/java/g1201_1300/s1283_find_the_smallest_divisor_given_a_threshold)| Medium | Array, Binary_Search | 9 | 95.49 - -#### Day 6 - -| | | | | | -|-|-|-|-|-|- -| 1898 |[Maximum Number of Removable Characters](src/main/java/g1801_1900/s1898_maximum_number_of_removable_characters)| Medium | Array, String, Binary_Search | 121 | 72.51 -| 1870 |[Minimum Speed to Arrive on Time](src/main/java/g1801_1900/s1870_minimum_speed_to_arrive_on_time)| Medium | Array, Binary_Search | 86 | 88.58 - -#### Day 7 - -| | | | | | -|-|-|-|-|-|- -| 1482 |[Minimum Number of Days to Make m Bouquets](src/main/java/g1401_1500/s1482_minimum_number_of_days_to_make_m_bouquets)| Medium | Array, Binary_Search | 25 | 69.18 -| 1818 |[Minimum Absolute Sum Difference](src/main/java/g1801_1900/s1818_minimum_absolute_sum_difference)| Medium | Array, Sorting, Binary_Search, Ordered_Set | 13 | 99.44 - -#### Day 8 - -| | | | | | -|-|-|-|-|-|- -| 0240 |[Search a 2D Matrix II](src/main/java/g0201_0300/s0240_search_a_2d_matrix_ii)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Binary_Search, Matrix, Divide_and_Conquer, Big_O_Time_O(n+m)_Space_O(1) | 7 | 86.73 -| 0275 |[H-Index II](src/main/java/g0201_0300/s0275_h_index_ii)| Medium | Array, Binary_Search | 0 | 100.00 - -#### Day 9 - -| | | | | | -|-|-|-|-|-|- -| 1838 |[Frequency of the Most Frequent Element](src/main/java/g1801_1900/s1838_frequency_of_the_most_frequent_element)| Medium | Array, Sorting, Greedy, Binary_Search, Prefix_Sum, Sliding_Window | 11 | 100.00 -| 0540 |[Single Element in a Sorted Array](src/main/java/g0501_0600/s0540_single_element_in_a_sorted_array)| Medium | Array, Binary_Search | 0 | 100.00 - -#### Day 10 - -| | | | | | -|-|-|-|-|-|- -| 0222 |[Count Complete Tree Nodes](src/main/java/g0201_0300/s0222_count_complete_tree_nodes)| Medium | Depth_First_Search, Tree, Binary_Search, Binary_Tree | 0 | 100.00 -| 1712 |[Ways to Split Array Into Three Subarrays](src/main/java/g1701_1800/s1712_ways_to_split_array_into_three_subarrays)| Medium | Array, Binary_Search, Two_Pointers, Prefix_Sum | 16 | 84.24 - -#### Day 11 - -| | | | | | -|-|-|-|-|-|- -| 0826 |[Most Profit Assigning Work](src/main/java/g0801_0900/s0826_most_profit_assigning_work)| Medium | Array, Sorting, Greedy, Binary_Search, Two_Pointers | 21 | 83.83 -| 0436 |[Find Right Interval](src/main/java/g0401_0500/s0436_find_right_interval)| Medium | Array, Sorting, Binary_Search | 20 | 81.51 - -#### Day 12 - -| | | | | | -|-|-|-|-|-|- -| 0081 |[Search in Rotated Sorted Array II](src/main/java/g0001_0100/s0081_search_in_rotated_sorted_array_ii)| Medium | Array, Binary_Search | 1 | 82.83 -| 0162 |[Find Peak Element](src/main/java/g0101_0200/s0162_find_peak_element)| Medium | Top_Interview_Questions, Array, Binary_Search | 0 | 100.00 - -#### Day 13 - -| | | | | | -|-|-|-|-|-|- -| 0154 |[Find Minimum in Rotated Sorted Array II](src/main/java/g0101_0200/s0154_find_minimum_in_rotated_sorted_array_ii)| Hard | Array, Binary_Search | 1 | 77.09 -| 0528 |[Random Pick with Weight](src/main/java/g0501_0600/s0528_random_pick_with_weight)| Medium | Math, Binary_Search, Prefix_Sum, Randomized | 42 | 50.90 - -#### Day 14 - -| | | | | | -|-|-|-|-|-|- -| 1508 |[Range Sum of Sorted Subarray Sums](src/main/java/g1501_1600/s1508_range_sum_of_sorted_subarray_sums)| Medium | Array, Sorting, Binary_Search, Two_Pointers | 60 | 93.84 -| 1574 |[Shortest Subarray to be Removed to Make Array Sorted](src/main/java/g1501_1600/s1574_shortest_subarray_to_be_removed_to_make_array_sorted)| Medium | Array, Binary_Search, Two_Pointers, Stack, Monotonic_Stack | 2 | 84.97 - -#### Day 15 - -| | | | | | -|-|-|-|-|-|- -| 1292 |[Maximum Side Length of a Square with Sum Less than or Equal to Threshold](src/main/java/g1201_1300/s1292_maximum_side_length_of_a_square_with_sum_less_than_or_equal_to_threshold)| Medium | Array, Binary_Search, Matrix, Prefix_Sum | 23 | 32.97 -| 1498 |[Number of Subsequences That Satisfy the Given Sum Condition](src/main/java/g1401_1500/s1498_number_of_subsequences_that_satisfy_the_given_sum_condition)| Medium | Array, Sorting, Binary_Search, Two_Pointers | 27 | 99.13 - -#### Day 16 - -| | | | | | -|-|-|-|-|-|- -| 0981 |[Time Based Key-Value Store](src/main/java/g0901_1000/s0981_time_based_key_value_store)| Medium | String, Hash_Table, Binary_Search, Design | 239 | 72.78 -| 1300 |[Sum of Mutated Array Closest to Target](src/main/java/g1201_1300/s1300_sum_of_mutated_array_closest_to_target)| Medium | Array, Sorting, Binary_Search | 7 | 33.33 - -#### Day 17 - -| | | | | | -|-|-|-|-|-|- -| 1802 |[Maximum Value at a Given Index in a Bounded Array](src/main/java/g1801_1900/s1802_maximum_value_at_a_given_index_in_a_bounded_array)| Medium | Greedy, Binary_Search | 2 | 58.44 -| 1901 |[Find a Peak Element II](src/main/java/g1901_2000/s1901_find_a_peak_element_ii)| Medium | Array, Binary_Search, Matrix, Divide_and_Conquer | 0 | 100.00 - -#### Day 18 - -| | | | | | -|-|-|-|-|-|- -| 1146 |[Snapshot Array](src/main/java/g1101_1200/s1146_snapshot_array)| Medium | Array, Hash_Table, Binary_Search, Design | 68 | 45.86 -| 1488 |[Avoid Flood in The City](src/main/java/g1401_1500/s1488_avoid_flood_in_the_city)| Medium | Array, Hash_Table, Greedy, Binary_Search, Heap_Priority_Queue | 82 | 75.08 - -#### Day 19 - -| | | | | | -|-|-|-|-|-|- -| 1562 |[Find Latest Group of Size M](src/main/java/g1501_1600/s1562_find_latest_group_of_size_m)| Medium | Array, Binary_Search, Simulation | 8 | 90.00 -| 1648 |[Sell Diminishing-Valued Colored Balls](src/main/java/g1601_1700/s1648_sell_diminishing_valued_colored_balls)| Medium | Array, Math, Sorting, Greedy, Binary_Search, Heap_Priority_Queue | 27 | 80.64 - -#### Day 20 - -| | | | | | -|-|-|-|-|-|- -| 1201 |[Ugly Number III](src/main/java/g1201_1300/s1201_ugly_number_iii)| Medium | Math, Binary_Search, Number_Theory | 0 | 100.00 -| 0911 |[Online Election](src/main/java/g0901_1000/s0911_online_election)| Medium | Array, Hash_Table, Binary_Search, Design | 63 | 98.81 +* [Binary Search II](#binary-search-ii) ### Dynamic Programming I @@ -947,7 +805,7 @@ | | | | | | |-|-|-|-|-|- | 0003 |[Longest Substring Without Repeating Characters](src/main/java/g0001_0100/s0003_longest_substring_without_repeating_characters)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, String, Hash_Table, Sliding_Window, Big_O_Time_O(n)_Space_O(1) | 2 | 99.52 -| 0016 |[3Sum Closest](src/main/java/g0001_0100/s0016_3sum_closest)| Medium | Array, Sorting, Two_Pointers | 3 | 99.88 +| 0016 |[3Sum Closest](src/main/java/g0001_0100/s0016_3sum_closest)| Medium | Array, Sorting, Two_Pointers | 4 | 98.21 | 0076 |[Minimum Window Substring](src/main/java/g0001_0100/s0076_minimum_window_substring)| Hard | Top_100_Liked_Questions, Top_Interview_Questions, String, Hash_Table, Sliding_Window, Big_O_Time_O(s.length())_Space_O(1) | 2 | 99.94 #### Day 15 Tree @@ -1015,7 +873,7 @@ | 0014 |[Longest Common Prefix](src/main/java/g0001_0100/s0014_longest_common_prefix)| Easy | Top_Interview_Questions, String | 0 | 100.00 | 0187 |[Repeated DNA Sequences](src/main/java/g0101_0200/s0187_repeated_dna_sequences)| Medium | String, Hash_Table, Bit_Manipulation, Sliding_Window, Hash_Function, Rolling_Hash | 29 | 77.11 | 0003 |[Longest Substring Without Repeating Characters](src/main/java/g0001_0100/s0003_longest_substring_without_repeating_characters)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, String, Hash_Table, Sliding_Window, Big_O_Time_O(n)_Space_O(1) | 2 | 99.52 -| 0020 |[Valid Parentheses](src/main/java/g0001_0100/s0020_valid_parentheses)| Easy | Top_100_Liked_Questions, Top_Interview_Questions, String, Stack, Big_O_Time_O(n)_Space_O(n) | 2 | 90.49 +| 0020 |[Valid Parentheses](src/main/java/g0001_0100/s0020_valid_parentheses)| Easy | Top_100_Liked_Questions, Top_Interview_Questions, String, Stack, Big_O_Time_O(n)_Space_O(n) | 1 | 98.78 | 0005 |[Longest Palindromic Substring](src/main/java/g0001_0100/s0005_longest_palindromic_substring)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, String, Dynamic_Programming, Big_O_Time_O(n)_Space_O(n) | 7 | 96.96 | 0394 |[Decode String](src/main/java/g0301_0400/s0394_decode_string)| Medium | Top_100_Liked_Questions, String, Stack, Recursion, Big_O_Time_O(n)_Space_O(n) | 1 | 87.68 | 0242 |[Valid Anagram](src/main/java/g0201_0300/s0242_valid_anagram)| Easy | Top_Interview_Questions, String, Hash_Table, Sorting | 2 | 99.01 @@ -1069,7 +927,7 @@ | 0977 |[Squares of a Sorted Array](src/main/java/g0901_1000/s0977_squares_of_a_sorted_array)| Easy | Array, Sorting, Two_Pointers | 1 | 100.00 | 0026 |[Remove Duplicates from Sorted Array](src/main/java/g0001_0100/s0026_remove_duplicates_from_sorted_array)| Easy | Top_Interview_Questions, Array, Two_Pointers | 1 | 98.56 | 0042 |[Trapping Rain Water](src/main/java/g0001_0100/s0042_trapping_rain_water)| Hard | Top_100_Liked_Questions, Top_Interview_Questions, Array, Dynamic_Programming, Two_Pointers, Stack, Monotonic_Stack, Big_O_Time_O(n)_Space_O(1) | 0 | 100.00 -| 0015 |[3Sum](src/main/java/g0001_0100/s0015_3sum)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Sorting, Two_Pointers, Big_O_Time_O(n\*log(n))_Space_O(n^2) | 27 | 97.93 +| 0015 |[3Sum](src/main/java/g0001_0100/s0015_3sum)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Sorting, Two_Pointers, Big_O_Time_O(n\*log(n))_Space_O(n^2) | 29 | 82.24 #### Udemy Famous Algorithm @@ -1272,7 +1130,7 @@ | | | | | | |-|-|-|-|-|- -| 0020 |[Valid Parentheses](src/main/java/g0001_0100/s0020_valid_parentheses)| Easy | Top_100_Liked_Questions, Top_Interview_Questions, String, Stack, Big_O_Time_O(n)_Space_O(n) | 2 | 90.49 +| 0020 |[Valid Parentheses](src/main/java/g0001_0100/s0020_valid_parentheses)| Easy | Top_100_Liked_Questions, Top_Interview_Questions, String, Stack, Big_O_Time_O(n)_Space_O(n) | 1 | 98.78 | 0232 |[Implement Queue using Stacks](src/main/java/g0201_0300/s0232_implement_queue_using_stacks)| Easy | Stack, Design, Queue | 1 | 67.21 #### Day 10 Tree @@ -1321,7 +1179,7 @@ |-|-|-|-|-|- | 0136 |[Single Number](src/main/java/g0101_0200/s0136_single_number)| Easy | Top_100_Liked_Questions, Top_Interview_Questions, Array, Bit_Manipulation, Big_O_Time_O(N)_Space_O(1) | 1 | 99.97 | 0169 |[Majority Element](src/main/java/g0101_0200/s0169_majority_element)| Easy | Top_100_Liked_Questions, Top_Interview_Questions, Array, Hash_Table, Sorting, Counting, Divide_and_Conquer, Big_O_Time_O(n)_Space_O(1) | 1 | 100.00 -| 0015 |[3Sum](src/main/java/g0001_0100/s0015_3sum)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Sorting, Two_Pointers, Big_O_Time_O(n\*log(n))_Space_O(n^2) | 27 | 97.93 +| 0015 |[3Sum](src/main/java/g0001_0100/s0015_3sum)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Sorting, Two_Pointers, Big_O_Time_O(n\*log(n))_Space_O(n^2) | 29 | 82.24 #### Day 2 Array @@ -1595,7 +1453,7 @@ | | | | | | |-|-|-|-|-|- | 0082 |[Remove Duplicates from Sorted List II](src/main/java/g0001_0100/s0082_remove_duplicates_from_sorted_list_ii)| Medium | Two_Pointers, Linked_List | 0 | 100.00 -| 0015 |[3Sum](src/main/java/g0001_0100/s0015_3sum)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Sorting, Two_Pointers, Big_O_Time_O(n\*log(n))_Space_O(n^2) | 27 | 97.93 +| 0015 |[3Sum](src/main/java/g0001_0100/s0015_3sum)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Sorting, Two_Pointers, Big_O_Time_O(n\*log(n))_Space_O(n^2) | 29 | 82.24 #### Day 4 Two Pointers @@ -1603,7 +1461,7 @@ |-|-|-|-|-|- | 0844 |[Backspace String Compare](src/main/java/g0801_0900/s0844_backspace_string_compare)| Easy | String, Two_Pointers, Stack, Simulation | 0 | 100.00 | 0986 |[Interval List Intersections](src/main/java/g0901_1000/s0986_interval_list_intersections)| Medium | Array, Two_Pointers | 2 | 99.95 -| 0011 |[Container With Most Water](src/main/java/g0001_0100/s0011_container_with_most_water)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Greedy, Two_Pointers, Big_O_Time_O(n)_Space_O(1) | 3 | 94.75 +| 0011 |[Container With Most Water](src/main/java/g0001_0100/s0011_container_with_most_water)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Greedy, Two_Pointers, Big_O_Time_O(n)_Space_O(1) | 3 | 95.71 #### Day 5 Sliding Window @@ -1812,6 +1670,148 @@ |-|-|-|-|-|- | 0153 |[Find Minimum in Rotated Sorted Array](src/main/java/g0101_0200/s0153_find_minimum_in_rotated_sorted_array)| Medium | Top_100_Liked_Questions, Array, Binary_Search, Big_O_Time_O(log_N)_Space_O(log_N) | 0 | 100.00 +### Binary Search II + +#### Day 1 + +| | | | | | +|-|-|-|-|-|- +| 0209 |[Minimum Size Subarray Sum](src/main/java/g0201_0300/s0209_minimum_size_subarray_sum)| Medium | Array, Binary_Search, Prefix_Sum, Sliding_Window | 1 | 100.00 +| 0611 |[Valid Triangle Number](src/main/java/g0601_0700/s0611_valid_triangle_number)| Medium | Array, Sorting, Greedy, Binary_Search, Two_Pointers | 10 | 100.00 + +#### Day 2 + +| | | | | | +|-|-|-|-|-|- +| 0658 |[Find K Closest Elements](src/main/java/g0601_0700/s0658_find_k_closest_elements)| Medium | Array, Sorting, Binary_Search, Two_Pointers, Heap_Priority_Queue | 3 | 99.20 +| 1894 |[Find the Student that Will Replace the Chalk](src/main/java/g1801_1900/s1894_find_the_student_that_will_replace_the_chalk)| Medium | Array, Binary_Search, Simulation, Prefix_Sum | 2 | 76.67 + +#### Day 3 + +| | | | | | +|-|-|-|-|-|- +| 0300 |[Longest Increasing Subsequence](src/main/java/g0201_0300/s0300_longest_increasing_subsequence)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Dynamic_Programming, Binary_Search, Big_O_Time_O(n\*log_n)_Space_O(n) | 3 | 98.63 +| 1760 |[Minimum Limit of Balls in a Bag](src/main/java/g1701_1800/s1760_minimum_limit_of_balls_in_a_bag)| Medium | Array, Binary_Search | 44 | 78.49 + +#### Day 4 + +| | | | | | +|-|-|-|-|-|- +| 0875 |[Koko Eating Bananas](src/main/java/g0801_0900/s0875_koko_eating_bananas)| Medium | Array, Binary_Search | 15 | 91.32 +| 1552 |[Magnetic Force Between Two Balls](src/main/java/g1501_1600/s1552_magnetic_force_between_two_balls)| Medium | Array, Sorting, Binary_Search | 39 | 99.65 + +#### Day 5 + +| | | | | | +|-|-|-|-|-|- +| 0287 |[Find the Duplicate Number](src/main/java/g0201_0300/s0287_find_the_duplicate_number)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Binary_Search, Two_Pointers, Bit_Manipulation, Big_O_Time_O(n)_Space_O(n) | 2 | 99.82 +| 1283 |[Find the Smallest Divisor Given a Threshold](src/main/java/g1201_1300/s1283_find_the_smallest_divisor_given_a_threshold)| Medium | Array, Binary_Search | 9 | 95.49 + +#### Day 6 + +| | | | | | +|-|-|-|-|-|- +| 1898 |[Maximum Number of Removable Characters](src/main/java/g1801_1900/s1898_maximum_number_of_removable_characters)| Medium | Array, String, Binary_Search | 121 | 72.51 +| 1870 |[Minimum Speed to Arrive on Time](src/main/java/g1801_1900/s1870_minimum_speed_to_arrive_on_time)| Medium | Array, Binary_Search | 86 | 88.58 + +#### Day 7 + +| | | | | | +|-|-|-|-|-|- +| 1482 |[Minimum Number of Days to Make m Bouquets](src/main/java/g1401_1500/s1482_minimum_number_of_days_to_make_m_bouquets)| Medium | Array, Binary_Search | 25 | 69.18 +| 1818 |[Minimum Absolute Sum Difference](src/main/java/g1801_1900/s1818_minimum_absolute_sum_difference)| Medium | Array, Sorting, Binary_Search, Ordered_Set | 13 | 99.44 + +#### Day 8 + +| | | | | | +|-|-|-|-|-|- +| 0240 |[Search a 2D Matrix II](src/main/java/g0201_0300/s0240_search_a_2d_matrix_ii)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Binary_Search, Matrix, Divide_and_Conquer, Big_O_Time_O(n+m)_Space_O(1) | 7 | 86.73 +| 0275 |[H-Index II](src/main/java/g0201_0300/s0275_h_index_ii)| Medium | Array, Binary_Search | 0 | 100.00 + +#### Day 9 + +| | | | | | +|-|-|-|-|-|- +| 1838 |[Frequency of the Most Frequent Element](src/main/java/g1801_1900/s1838_frequency_of_the_most_frequent_element)| Medium | Array, Sorting, Greedy, Binary_Search, Prefix_Sum, Sliding_Window | 11 | 100.00 +| 0540 |[Single Element in a Sorted Array](src/main/java/g0501_0600/s0540_single_element_in_a_sorted_array)| Medium | Array, Binary_Search | 0 | 100.00 + +#### Day 10 + +| | | | | | +|-|-|-|-|-|- +| 0222 |[Count Complete Tree Nodes](src/main/java/g0201_0300/s0222_count_complete_tree_nodes)| Medium | Depth_First_Search, Tree, Binary_Search, Binary_Tree | 0 | 100.00 +| 1712 |[Ways to Split Array Into Three Subarrays](src/main/java/g1701_1800/s1712_ways_to_split_array_into_three_subarrays)| Medium | Array, Binary_Search, Two_Pointers, Prefix_Sum | 16 | 84.24 + +#### Day 11 + +| | | | | | +|-|-|-|-|-|- +| 0826 |[Most Profit Assigning Work](src/main/java/g0801_0900/s0826_most_profit_assigning_work)| Medium | Array, Sorting, Greedy, Binary_Search, Two_Pointers | 21 | 83.83 +| 0436 |[Find Right Interval](src/main/java/g0401_0500/s0436_find_right_interval)| Medium | Array, Sorting, Binary_Search | 20 | 81.51 + +#### Day 12 + +| | | | | | +|-|-|-|-|-|- +| 0081 |[Search in Rotated Sorted Array II](src/main/java/g0001_0100/s0081_search_in_rotated_sorted_array_ii)| Medium | Array, Binary_Search | 1 | 82.83 +| 0162 |[Find Peak Element](src/main/java/g0101_0200/s0162_find_peak_element)| Medium | Top_Interview_Questions, Array, Binary_Search | 0 | 100.00 + +#### Day 13 + +| | | | | | +|-|-|-|-|-|- +| 0154 |[Find Minimum in Rotated Sorted Array II](src/main/java/g0101_0200/s0154_find_minimum_in_rotated_sorted_array_ii)| Hard | Array, Binary_Search | 1 | 77.09 +| 0528 |[Random Pick with Weight](src/main/java/g0501_0600/s0528_random_pick_with_weight)| Medium | Math, Binary_Search, Prefix_Sum, Randomized | 42 | 50.90 + +#### Day 14 + +| | | | | | +|-|-|-|-|-|- +| 1508 |[Range Sum of Sorted Subarray Sums](src/main/java/g1501_1600/s1508_range_sum_of_sorted_subarray_sums)| Medium | Array, Sorting, Binary_Search, Two_Pointers | 60 | 93.84 +| 1574 |[Shortest Subarray to be Removed to Make Array Sorted](src/main/java/g1501_1600/s1574_shortest_subarray_to_be_removed_to_make_array_sorted)| Medium | Array, Binary_Search, Two_Pointers, Stack, Monotonic_Stack | 2 | 84.97 + +#### Day 15 + +| | | | | | +|-|-|-|-|-|- +| 1292 |[Maximum Side Length of a Square with Sum Less than or Equal to Threshold](src/main/java/g1201_1300/s1292_maximum_side_length_of_a_square_with_sum_less_than_or_equal_to_threshold)| Medium | Array, Binary_Search, Matrix, Prefix_Sum | 23 | 32.97 +| 1498 |[Number of Subsequences That Satisfy the Given Sum Condition](src/main/java/g1401_1500/s1498_number_of_subsequences_that_satisfy_the_given_sum_condition)| Medium | Array, Sorting, Binary_Search, Two_Pointers | 27 | 99.13 + +#### Day 16 + +| | | | | | +|-|-|-|-|-|- +| 0981 |[Time Based Key-Value Store](src/main/java/g0901_1000/s0981_time_based_key_value_store)| Medium | String, Hash_Table, Binary_Search, Design | 239 | 72.78 +| 1300 |[Sum of Mutated Array Closest to Target](src/main/java/g1201_1300/s1300_sum_of_mutated_array_closest_to_target)| Medium | Array, Sorting, Binary_Search | 7 | 33.33 + +#### Day 17 + +| | | | | | +|-|-|-|-|-|- +| 1802 |[Maximum Value at a Given Index in a Bounded Array](src/main/java/g1801_1900/s1802_maximum_value_at_a_given_index_in_a_bounded_array)| Medium | Greedy, Binary_Search | 2 | 58.44 +| 1901 |[Find a Peak Element II](src/main/java/g1901_2000/s1901_find_a_peak_element_ii)| Medium | Array, Binary_Search, Matrix, Divide_and_Conquer | 0 | 100.00 + +#### Day 18 + +| | | | | | +|-|-|-|-|-|- +| 1146 |[Snapshot Array](src/main/java/g1101_1200/s1146_snapshot_array)| Medium | Array, Hash_Table, Binary_Search, Design | 68 | 45.86 +| 1488 |[Avoid Flood in The City](src/main/java/g1401_1500/s1488_avoid_flood_in_the_city)| Medium | Array, Hash_Table, Greedy, Binary_Search, Heap_Priority_Queue | 82 | 75.08 + +#### Day 19 + +| | | | | | +|-|-|-|-|-|- +| 1562 |[Find Latest Group of Size M](src/main/java/g1501_1600/s1562_find_latest_group_of_size_m)| Medium | Array, Binary_Search, Simulation | 8 | 90.00 +| 1648 |[Sell Diminishing-Valued Colored Balls](src/main/java/g1601_1700/s1648_sell_diminishing_valued_colored_balls)| Medium | Array, Math, Sorting, Greedy, Binary_Search, Heap_Priority_Queue | 27 | 80.64 + +#### Day 20 + +| | | | | | +|-|-|-|-|-|- +| 1201 |[Ugly Number III](src/main/java/g1201_1300/s1201_ugly_number_iii)| Medium | Math, Binary_Search, Number_Theory | 0 | 100.00 +| 0911 |[Online Election](src/main/java/g0901_1000/s0911_online_election)| Medium | Array, Hash_Table, Binary_Search, Design | 63 | 98.81 + ## Algorithms | # | Title | Difficulty | Tag | Time, ms | Time, % @@ -4195,16 +4195,16 @@ | 0023 |[Merge k Sorted Lists](src/main/java/g0001_0100/s0023_merge_k_sorted_lists)| Hard | Top_100_Liked_Questions, Top_Interview_Questions, Heap_Priority_Queue, Linked_List, Divide_and_Conquer, Merge_Sort, Big_O_Time_O(k\*n\*log(k))_Space_O(log(k)) | 1 | 100.00 | 0022 |[Generate Parentheses](src/main/java/g0001_0100/s0022_generate_parentheses)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, String, Dynamic_Programming, Backtracking, Algorithm_II_Day_11_Recursion_Backtracking, Udemy_Backtracking/Recursion, Big_O_Time_O(2^n)_Space_O(n) | 0 | 100.00 | 0021 |[Merge Two Sorted Lists](src/main/java/g0001_0100/s0021_merge_two_sorted_lists)| Easy | Top_100_Liked_Questions, Top_Interview_Questions, Linked_List, Recursion, Data_Structure_I_Day_7_Linked_List, Algorithm_I_Day_10_Recursion_Backtracking, Level_1_Day_3_Linked_List, Udemy_Linked_List, Big_O_Time_O(m+n)_Space_O(m+n) | 0 | 100.00 -| 0020 |[Valid Parentheses](src/main/java/g0001_0100/s0020_valid_parentheses)| Easy | Top_100_Liked_Questions, Top_Interview_Questions, String, Stack, Data_Structure_I_Day_9_Stack_Queue, Udemy_Strings, Big_O_Time_O(n)_Space_O(n) | 2 | 90.49 +| 0020 |[Valid Parentheses](src/main/java/g0001_0100/s0020_valid_parentheses)| Easy | Top_100_Liked_Questions, Top_Interview_Questions, String, Stack, Data_Structure_I_Day_9_Stack_Queue, Udemy_Strings, Big_O_Time_O(n)_Space_O(n) | 1 | 98.78 | 0019 |[Remove Nth Node From End of List](src/main/java/g0001_0100/s0019_remove_nth_node_from_end_of_list)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Two_Pointers, Linked_List, Algorithm_I_Day_5_Two_Pointers, Level_2_Day_3_Linked_List, Big_O_Time_O(L)_Space_O(L) | 0 | 100.00 -| 0018 |[4Sum](src/main/java/g0001_0100/s0018_4sum)| Medium | Array, Sorting, Two_Pointers | 3 | 99.77 +| 0018 |[4Sum](src/main/java/g0001_0100/s0018_4sum)| Medium | Array, Sorting, Two_Pointers | 3 | 99.69 | 0017 |[Letter Combinations of a Phone Number](src/main/java/g0001_0100/s0017_letter_combinations_of_a_phone_number)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, String, Hash_Table, Backtracking, Algorithm_II_Day_11_Recursion_Backtracking, Udemy_Backtracking/Recursion, Big_O_Time_O(4^n)_Space_O(n) | 0 | 100.00 -| 0016 |[3Sum Closest](src/main/java/g0001_0100/s0016_3sum_closest)| Medium | Array, Sorting, Two_Pointers, Level_2_Day_14_Sliding_Window/Two_Pointer | 3 | 99.88 -| 0015 |[3Sum](src/main/java/g0001_0100/s0015_3sum)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Sorting, Two_Pointers, Data_Structure_II_Day_1_Array, Algorithm_II_Day_3_Two_Pointers, Udemy_Two_Pointers, Big_O_Time_O(n\*log(n))_Space_O(n^2) | 27 | 97.93 +| 0016 |[3Sum Closest](src/main/java/g0001_0100/s0016_3sum_closest)| Medium | Array, Sorting, Two_Pointers, Level_2_Day_14_Sliding_Window/Two_Pointer | 4 | 98.21 +| 0015 |[3Sum](src/main/java/g0001_0100/s0015_3sum)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Sorting, Two_Pointers, Data_Structure_II_Day_1_Array, Algorithm_II_Day_3_Two_Pointers, Udemy_Two_Pointers, Big_O_Time_O(n\*log(n))_Space_O(n^2) | 29 | 82.24 | 0014 |[Longest Common Prefix](src/main/java/g0001_0100/s0014_longest_common_prefix)| Easy | Top_Interview_Questions, String, Level_2_Day_2_String, Udemy_Strings | 0 | 100.00 | 0013 |[Roman to Integer](src/main/java/g0001_0100/s0013_roman_to_integer)| Easy | Top_Interview_Questions, String, Hash_Table, Math | 2 | 100.00 | 0012 |[Integer to Roman](src/main/java/g0001_0100/s0012_integer_to_roman)| Medium | String, Hash_Table, Math | 2 | 100.00 -| 0011 |[Container With Most Water](src/main/java/g0001_0100/s0011_container_with_most_water)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Greedy, Two_Pointers, Algorithm_II_Day_4_Two_Pointers, Big_O_Time_O(n)_Space_O(1) | 3 | 94.75 +| 0011 |[Container With Most Water](src/main/java/g0001_0100/s0011_container_with_most_water)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Greedy, Two_Pointers, Algorithm_II_Day_4_Two_Pointers, Big_O_Time_O(n)_Space_O(1) | 3 | 95.71 | 0010 |[Regular Expression Matching](src/main/java/g0001_0100/s0010_regular_expression_matching)| Hard | Top_100_Liked_Questions, Top_Interview_Questions, String, Dynamic_Programming, Recursion, Udemy_Dynamic_Programming, Big_O_Time_O(m\*n)_Space_O(m\*n) | 1 | 100.00 | 0009 |[Palindrome Number](src/main/java/g0001_0100/s0009_palindrome_number)| Easy | Math, Udemy_Integers | 5 | 77.91 | 0008 |[String to Integer (atoi)](src/main/java/g0001_0100/s0008_string_to_integer_atoi)| Medium | Top_Interview_Questions, String | 1 | 100.00 diff --git a/src/main/java/g0001_0100/s0001_two_sum/readme.md b/src/main/java/g0001_0100/s0001_two_sum/readme.md index fadd09dd..a0515823 100644 --- a/src/main/java/g0001_0100/s0001_two_sum/readme.md +++ b/src/main/java/g0001_0100/s0001_two_sum/readme.md @@ -40,44 +40,64 @@ You can return the answer in any order. **Follow-up:** Can you come up with an algorithm that is less than O(n2) time complexity? -## Solution +To solve the Two Sum problem in Java using a `Solution` class, we'll follow these steps: + +1. Define a `Solution` class with a method named `twoSum`. +2. Inside the `twoSum` method, create a hashmap to store elements and their indices. +3. Iterate through the array: + - For each element, calculate the complement required to reach the target sum. + - Check if the complement exists in the hashmap. + - If found, return the indices of the current element and the complement. + - If not found, add the current element and its index to the hashmap. +4. Handle edge cases: + - If no solution is found, return an empty array or null (depending on the problem requirements). + +Here's the implementation: ```java import java.util.HashMap; -import java.util.Map; public class Solution { - public int[] twoSum(int[] numbers, int target) { - Map indexMap = new HashMap<>(); - for (int i = 0; i < numbers.length; i++) { - Integer requiredNum = target - numbers[i]; - if (indexMap.containsKey(requiredNum)) { - return new int[] {indexMap.get(requiredNum), i}; + + public int[] twoSum(int[] nums, int target) { + // Create a hashmap to store elements and their indices + HashMap map = new HashMap<>(); + + // Iterate through the array + for (int i = 0; i < nums.length; i++) { + int complement = target - nums[i]; + // Check if the complement exists in the hashmap + if (map.containsKey(complement)) { + // Return the indices of the current element and the complement + return new int[]{map.get(complement), i}; } - indexMap.put(numbers[i], i); + // Add the current element and its index to the hashmap + map.put(nums[i], i); } - return new int[] {-1, -1}; + // If no solution is found, return an empty array or null + return new int[]{}; + } + + public static void main(String[] args) { + Solution solution = new Solution(); + + // Test cases + int[] nums1 = {2, 7, 11, 15}; + int target1 = 9; + int[] result1 = solution.twoSum(nums1, target1); + System.out.println("Example 1 Output: [" + result1[0] + ", " + result1[1] + "]"); + + int[] nums2 = {3, 2, 4}; + int target2 = 6; + int[] result2 = solution.twoSum(nums2, target2); + System.out.println("Example 2 Output: [" + result2[0] + ", " + result2[1] + "]"); + + int[] nums3 = {3, 3}; + int target3 = 6; + int[] result3 = solution.twoSum(nums3, target3); + System.out.println("Example 3 Output: [" + result3[0] + ", " + result3[1] + "]"); } } ``` -**Time Complexity (Big O Time):** - -The time complexity of this program is O(n), where "n" represents the number of elements in the `numbers` array. Here's the breakdown: - -1. The program iterates through the `numbers` array once using a `for` loop, which runs for "n" iterations (n is the length of the array). -2. Inside the loop, it performs constant-time operations: - - It calculates the `requiredNum` (constant time). - - It checks if `requiredNum` is present in the `indexMap` (constant time). - - It puts `numbers[i]` and `i` into the `indexMap` (constant time). - -Since all the operations inside the loop are constant time, and the loop itself runs for "n" iterations, the overall time complexity is O(n). - -**Space Complexity (Big O Space):** - -The space complexity of this program is also O(n), where "n" represents the number of elements in the `numbers` array. Here's why: - -1. The program uses a `Map` called `indexMap` to store the numbers and their corresponding indices. In the worst case, it could store all "n" elements from the `numbers` array. -2. The program returns an integer array of size 2 (constant space), regardless of the input size. - -The dominant factor in terms of space complexity is the `indexMap`, which can potentially store "n" key-value pairs. Therefore, the space complexity is O(n). +This implementation provides a solution to the Two Sum problem with a time complexity of O(n), where n is the number of elements in the input array. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0002_add_two_numbers/readme.md b/src/main/java/g0001_0100/s0002_add_two_numbers/readme.md index 8d7d7162..b6840e8f 100644 --- a/src/main/java/g0001_0100/s0002_add_two_numbers/readme.md +++ b/src/main/java/g0001_0100/s0002_add_two_numbers/readme.md @@ -37,65 +37,100 @@ You may assume the two numbers do not contain any leading zero, except the numbe * `0 <= Node.val <= 9` * It is guaranteed that the list represents a number that does not have leading zeros. -## Solution +To solve the Add Two Numbers problem in Java using a `Solution` class, we'll follow these steps: + +1. Define a `ListNode` class to represent nodes in a linked list. +2. Define a `Solution` class with a method named `addTwoNumbers`. +3. Inside the `addTwoNumbers` method, traverse both input linked lists simultaneously: + - Keep track of a carry variable to handle cases where the sum of two digits exceeds 9. + - Calculate the sum of the current nodes' values along with the carry. + - Update the carry for the next iteration. + - Create a new node with the sum % 10 and attach it to the result linked list. + - Move to the next nodes in both input lists. +4. After finishing the traversal, check if there is any remaining carry. If so, add a new node with the carry to the result. +5. Return the head of the result linked list. + +Here's the implementation: ```java -import com_github_leetcode.ListNode; - -/* - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode(int x) { val = x; } - * } - */ +class ListNode { + int val; + ListNode next; + + ListNode() {} + + ListNode(int val) { + this.val = val; + } + + ListNode(int val, ListNode next) { + this.val = val; + this.next = next; + } +} + public class Solution { + public ListNode addTwoNumbers(ListNode l1, ListNode l2) { - ListNode dummyHead = new ListNode(0); - ListNode p = l1; - ListNode q = l2; + ListNode dummyHead = new ListNode(); ListNode curr = dummyHead; int carry = 0; - while (p != null || q != null) { - int x = (p != null) ? p.val : 0; - int y = (q != null) ? q.val : 0; - int sum = carry + x + y; - carry = sum / 10; - curr.next = new ListNode(sum % 10); - curr = curr.next; - if (p != null) { - p = p.next; + + while (l1 != null || l2 != null) { + int sum = carry; + if (l1 != null) { + sum += l1.val; + l1 = l1.next; } - if (q != null) { - q = q.next; + if (l2 != null) { + sum += l2.val; + l2 = l2.next; } + curr.next = new ListNode(sum % 10); + curr = curr.next; + carry = sum / 10; } + if (carry > 0) { curr.next = new ListNode(carry); } + return dummyHead.next; } -} -``` - -**Time Complexity (Big O Time):** - -The time complexity of this program is O(max(N, M)), where "N" and "M" represent the lengths of the input linked lists `l1` and `l2`, respectively. Here's the breakdown: - -1. The program iterates through both linked lists `l1` and `l2` simultaneously using a `while` loop. The loop runs as long as either of the two lists has elements to process. -2. Inside the loop, it performs constant-time operations for each node: - - It calculates the sum of three integer values (constant time). - - It creates a new node (constant time). - - It updates pointers and variables (constant time). - -Since the loop runs until the end of the longer of the two input linked lists, the overall time complexity is O(max(N, M)), where "N" and "M" are the lengths of `l1` and `l2`, respectively. - -**Space Complexity (Big O Space):** -The space complexity of this program is O(max(N, M)), which is primarily determined by the space used for the output linked list. Here's why: + // Helper method to print a linked list + public void printList(ListNode head) { + ListNode curr = head; + while (curr != null) { + System.out.print(curr.val + " "); + curr = curr.next; + } + System.out.println(); + } -1. The program creates a new linked list to store the result, and the length of this linked list can be at most max(N, M) + 1 (where +1 is for the potential carry at the end). -2. Other than the output linked list, the program uses a constant amount of space for variables like `dummyHead`, `p`, `q`, `curr`, and `carry`. + public static void main(String[] args) { + Solution solution = new Solution(); + + // Test cases + ListNode l1 = new ListNode(2, new ListNode(4, new ListNode(3))); + ListNode l2 = new ListNode(5, new ListNode(6, new ListNode(4))); + ListNode result1 = solution.addTwoNumbers(l1, l2); + System.out.print("Example 1 Output: "); + solution.printList(result1); + + ListNode l3 = new ListNode(0); + ListNode l4 = new ListNode(0); + ListNode result2 = solution.addTwoNumbers(l3, l4); + System.out.print("Example 2 Output: "); + solution.printList(result2); + + ListNode l5 = new ListNode(9, new ListNode(9, new ListNode(9, new ListNode(9, new ListNode(9, new ListNode(9, new ListNode(9))))))); + ListNode l6 = new ListNode(9, new ListNode(9, new ListNode(9, new ListNode(9))))); + ListNode result3 = solution.addTwoNumbers(l5, l6); + System.out.print("Example 3 Output: "); + solution.printList(result3); + } +} +``` -Therefore, the space complexity is O(max(N, M)). +This implementation provides a solution to the Add Two Numbers problem using linked lists in Java. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0003_longest_substring_without_repeating_characters/readme.md b/src/main/java/g0001_0100/s0003_longest_substring_without_repeating_characters/readme.md index 940f4d76..902edd60 100644 --- a/src/main/java/g0001_0100/s0003_longest_substring_without_repeating_characters/readme.md +++ b/src/main/java/g0001_0100/s0003_longest_substring_without_repeating_characters/readme.md @@ -42,54 +42,65 @@ Given a string `s`, find the length of the **longest substring** without repeati * 0 <= s.length <= 5 * 104 * `s` consists of English letters, digits, symbols and spaces. -## Solution +To solve the Longest Substring Without Repeating Characters problem in Java using a `Solution` class, we'll follow these steps: + +1. Define a `Solution` class with a method named `lengthOfLongestSubstring`. +2. Initialize variables to keep track of the starting index of the substring (`start`), the maximum length (`maxLen`), and a hashmap to store characters and their indices. +3. Iterate through the string `s`, and for each character: + - Check if the character exists in the hashmap and its index is greater than or equal to the `start` index. + - If found, update the `start` index to the index after the last occurrence of the character. + - Update the maximum length if necessary. + - Update the index of the current character in the hashmap. +4. Return the maximum length found. +5. Handle the edge case where the input string is empty. + +Here's the implementation: ```java +import java.util.HashMap; + public class Solution { + public int lengthOfLongestSubstring(String s) { - int[] lastIndices = new int[256]; - for (int i = 0; i < 256; i++) { - lastIndices[i] = -1; - } - int maxLen = 0; - int curLen = 0; + // Initialize variables int start = 0; - for (int i = 0; i < s.length(); i++) { - char cur = s.charAt(i); - if (lastIndices[cur] < start) { - lastIndices[cur] = i; - curLen++; - } else { - int lastIndex = lastIndices[cur]; - start = lastIndex + 1; - curLen = i - start + 1; - lastIndices[cur] = i; - } - if (curLen > maxLen) { - maxLen = curLen; + int maxLen = 0; + HashMap map = new HashMap<>(); + + // Iterate through the string + for (int end = 0; end < s.length(); end++) { + char ch = s.charAt(end); + // If the character exists in the hashmap and its index is greater than or equal to the start index + if (map.containsKey(ch) && map.get(ch) >= start) { + // Update the start index to the index after the last occurrence of the character + start = map.get(ch) + 1; } + // Update the maximum length if necessary + maxLen = Math.max(maxLen, end - start + 1); + // Update the index of the current character in the hashmap + map.put(ch, end); } + return maxLen; } -} -``` - -**Time Complexity (Big O Time):** - -The time complexity of this program is O(n), where "n" represents the length of the input string `s`. Here's the breakdown: -1. The program iterates through the characters of the input string `s` using a `for` loop, and this loop runs for "n" iterations, where "n" is the length of `s`. -2. Inside the loop, it performs constant-time operations: - - Initializing the `lastIndices` array (constant time). - - Updating values in the `lastIndices` array (constant time). - - Updating variables like `maxLen`, `curLen`, `start`, and `lastIndices[cur]` (constant time). + public static void main(String[] args) { + Solution solution = new Solution(); -Since the loop runs for "n" iterations, and all operations inside the loop are constant time, the overall time complexity is O(n). + // Test cases + String s1 = "abcabcbb"; + System.out.println("Example 1 Output: " + solution.lengthOfLongestSubstring(s1)); -**Space Complexity (Big O Space):** + String s2 = "bbbbb"; + System.out.println("Example 2 Output: " + solution.lengthOfLongestSubstring(s2)); -The space complexity of this program is O(256) = O(1), as it uses a fixed-size array `lastIndices` of length 256 to store the last indices of characters. This array's size does not depend on the input size and remains constant. + String s3 = "pwwkew"; + System.out.println("Example 3 Output: " + solution.lengthOfLongestSubstring(s3)); -Additionally, the program uses a few integer variables and constant space to store the result. The space used for these variables does not depend on the input size and is also considered constant. + String s4 = ""; + System.out.println("Example 4 Output: " + solution.lengthOfLongestSubstring(s4)); + } +} +``` -Therefore, the space complexity is O(1), or more precisely, O(256), which is still considered constant because it doesn't grow with the input size. +This implementation provides a solution to the Longest Substring Without Repeating Characters problem in Java. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0004_median_of_two_sorted_arrays/readme.md b/src/main/java/g0001_0100/s0004_median_of_two_sorted_arrays/readme.md index 297701ac..048495aa 100644 --- a/src/main/java/g0001_0100/s0004_median_of_two_sorted_arrays/readme.md +++ b/src/main/java/g0001_0100/s0004_median_of_two_sorted_arrays/readme.md @@ -52,56 +52,70 @@ The overall run time complexity should be `O(log (m+n))`. * `1 <= m + n <= 2000` * -106 <= nums1[i], nums2[i] <= 106 -## Solution +To solve the Median of Two Sorted Arrays problem in Java using a `Solution` class, we'll follow these steps: + +1. Define a `Solution` class with a method named `findMedianSortedArrays`. +2. Calculate the total length of the combined array (m + n). +3. Determine the middle index or indices of the combined array based on its length (for both even and odd lengths). +4. Implement a binary search algorithm to find the correct position for partitioning the two arrays such that elements to the left are less than or equal to elements on the right. +5. Calculate the median based on the partitioned arrays. +6. Handle edge cases where one or both arrays are empty or where the combined length is odd or even. +7. Return the calculated median. + +Here's the implementation: ```java -@SuppressWarnings("java:S2234") public class Solution { + public double findMedianSortedArrays(int[] nums1, int[] nums2) { - if (nums2.length < nums1.length) { - return findMedianSortedArrays(nums2, nums1); - } - int cut1; - int cut2; - int n1 = nums1.length; - int n2 = nums2.length; - int low = 0; - int high = n1; - while (low <= high) { - cut1 = (low + high) / 2; - cut2 = ((n1 + n2 + 1) / 2) - cut1; - int l1 = cut1 == 0 ? Integer.MIN_VALUE : nums1[cut1 - 1]; - int l2 = cut2 == 0 ? Integer.MIN_VALUE : nums2[cut2 - 1]; - int r1 = cut1 == n1 ? Integer.MAX_VALUE : nums1[cut1]; - int r2 = cut2 == n2 ? Integer.MAX_VALUE : nums2[cut2]; - if (l1 <= r2 && l2 <= r1) { - if ((n1 + n2) % 2 == 0) { - return (Math.max(l1, l2) + Math.min(r1, r2)) / 2.0; - } - return Math.max(l1, l2); - } else if (l1 > r2) { - high = cut1 - 1; - } else { - low = cut1 + 1; - } + int m = nums1.length; + int n = nums2.length; + int totalLength = m + n; + int left = (totalLength + 1) / 2; + int right = (totalLength + 2) / 2; + return (findKth(nums1, 0, nums2, 0, left) + findKth(nums1, 0, nums2, 0, right)) / 2.0; + } + + private int findKth(int[] nums1, int i, int[] nums2, int j, int k) { + if (i >= nums1.length) return nums2[j + k - 1]; + if (j >= nums2.length) return nums1[i + k - 1]; + if (k == 1) return Math.min(nums1[i], nums2[j]); + + int midVal1 = (i + k / 2 - 1 < nums1.length) ? nums1[i + k / 2 - 1] : Integer.MAX_VALUE; + int midVal2 = (j + k / 2 - 1 < nums2.length) ? nums2[j + k / 2 - 1] : Integer.MAX_VALUE; + + if (midVal1 < midVal2) { + return findKth(nums1, i + k / 2, nums2, j, k - k / 2); + } else { + return findKth(nums1, i, nums2, j + k / 2, k - k / 2); } - return 0.0f; } -} -``` -**Time Complexity (Big O Time):** + public static void main(String[] args) { + Solution solution = new Solution(); -The time complexity of this program is O(log(min(N, M))), where "N" and "M" represent the lengths of the input arrays `nums1` and `nums2`, respectively. Here's the breakdown: + // Test cases + int[] nums1_1 = {1, 3}; + int[] nums2_1 = {2}; + System.out.println("Example 1 Output: " + solution.findMedianSortedArrays(nums1_1, nums2_1)); -1. The program uses a binary search algorithm to find the median of the two sorted arrays. -2. The binary search operates on the smaller of the two input arrays. This choice ensures that the search is performed on the shorter array, which reduces the number of iterations. -3. In each iteration of the binary search, the program performs constant-time operations. These operations include arithmetic calculations, comparisons, and array access. + int[] nums1_2 = {1, 2}; + int[] nums2_2 = {3, 4}; + System.out.println("Example 2 Output: " + solution.findMedianSortedArrays(nums1_2, nums2_2)); -Since the binary search reduces the search space by half in each iteration, the time complexity of this algorithm is O(log(min(N, M))), where "N" and "M" are the lengths of the input arrays `nums1` and `nums2`, respectively. + int[] nums1_3 = {0, 0}; + int[] nums2_3 = {0, 0}; + System.out.println("Example 3 Output: " + solution.findMedianSortedArrays(nums1_3, nums2_3)); -**Space Complexity (Big O Space):** + int[] nums1_4 = {}; + int[] nums2_4 = {1}; + System.out.println("Example 4 Output: " + solution.findMedianSortedArrays(nums1_4, nums2_4)); -The space complexity of this program is O(1), which means it uses a constant amount of extra space that does not depend on the input size. The program uses a few integer variables (`cut1`, `cut2`, `n1`, `n2`, `low`, `high`, `l1`, `l2`, `r1`, and `r2`) to keep track of indices and values during the binary search. These variables take up a constant amount of space, regardless of the input size. + int[] nums1_5 = {2}; + int[] nums2_5 = {}; + System.out.println("Example 5 Output: " + solution.findMedianSortedArrays(nums1_5, nums2_5)); + } +} +``` -Therefore, the space complexity is O(1). +This implementation provides a solution to the Median of Two Sorted Arrays problem in Java with a runtime complexity of O(log(min(m, n))). \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0005_longest_palindromic_substring/readme.md b/src/main/java/g0001_0100/s0005_longest_palindromic_substring/readme.md index 0988c2a3..a8d8432d 100644 --- a/src/main/java/g0001_0100/s0005_longest_palindromic_substring/readme.md +++ b/src/main/java/g0001_0100/s0005_longest_palindromic_substring/readme.md @@ -36,66 +36,65 @@ Given a string `s`, return _the longest palindromic substring_ in `s`. * `1 <= s.length <= 1000` * `s` consist of only digits and English letters. -## Solution +To solve the Longest Palindromic Substring problem in Java using a `Solution` class, we'll follow these steps: + +1. Define a `Solution` class with a method named `longestPalindrome`. +2. Initialize variables to keep track of the start and end indices of the longest palindromic substring found so far (`start` and `end`). +3. Iterate through the string `s`: + - For each character in the string, expand around it to check if it forms a palindrome. + - Handle both odd-length and even-length palindromes separately. + - Update `start` and `end` indices if a longer palindrome is found. +4. Return the substring from `start` to `end`. +5. Handle edge cases where the input string is empty or has a length of 1. + +Here's the implementation: ```java public class Solution { + public String longestPalindrome(String s) { - char[] newStr = new char[s.length() * 2 + 1]; - newStr[0] = '#'; + if (s == null || s.length() < 1) return ""; + int start = 0; + int end = 0; + for (int i = 0; i < s.length(); i++) { - newStr[2 * i + 1] = s.charAt(i); - newStr[2 * i + 2] = '#'; - } - int[] dp = new int[newStr.length]; - int friendCenter = 0; - int friendRadius = 0; - int lpsCenter = 0; - int lpsRadius = 0; - for (int i = 0; i < newStr.length; i++) { - dp[i] = - friendCenter + friendRadius > i - ? Math.min(dp[friendCenter * 2 - i], (friendCenter + friendRadius) - i) - : 1; - while (i + dp[i] < newStr.length - && i - dp[i] >= 0 - && newStr[i + dp[i]] == newStr[i - dp[i]]) { - dp[i]++; - } - if (friendCenter + friendRadius < i + dp[i]) { - friendCenter = i; - friendRadius = dp[i]; - } - if (lpsRadius < dp[i]) { - lpsCenter = i; - lpsRadius = dp[i]; + int len1 = expandAroundCenter(s, i, i); + int len2 = expandAroundCenter(s, i, i + 1); + int len = Math.max(len1, len2); + if (len > end - start) { + start = i - (len - 1) / 2; + end = i + len / 2; } } - return s.substring((lpsCenter - lpsRadius + 1) / 2, (lpsCenter + lpsRadius - 1) / 2); + + return s.substring(start, end + 1); + } + + private int expandAroundCenter(String s, int left, int right) { + while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) { + left--; + right++; + } + return right - left - 1; } -} -``` - -**Time Complexity (Big O Time):** - -The time complexity of this program is O(n), where "n" represents the length of the input string `s`. Here's the breakdown: - -1. The program first creates a new string `newStr` by inserting '#' characters between each character in the original string `s`. This operation has a time complexity of O(n) because it processes each character of `s`. - -2. After creating `newStr`, the program uses the Manacher's Algorithm to find the longest palindromic substring. This algorithm is known to have a linear time complexity of O(n). - -3. The loop that implements Manacher's Algorithm iterates through the characters of `newStr`. In each iteration, it performs constant-time operations like comparisons and arithmetic calculations. The key operation within this loop is the palindrome expansion, which extends the palindrome around the current center. The loop iterates through `newStr` only once, and each expansion step performs constant work. - -Therefore, the overall time complexity of the program is dominated by the linear-time Manacher's Algorithm, making it O(n). -**Space Complexity (Big O Space):** + public static void main(String[] args) { + Solution solution = new Solution(); -The space complexity of this program is O(n), where "n" represents the length of the input string `s`. Here's why: + // Test cases + String s1 = "babad"; + System.out.println("Example 1 Output: " + solution.longestPalindrome(s1)); -1. The program creates a new character array `newStr` with a length of `s.length() * 2 + 1`. This array stores a modified version of the input string `s` with '#' characters inserted. The space used by `newStr` is proportional to the length of `s`, so it has a space complexity of O(n). + String s2 = "cbbd"; + System.out.println("Example 2 Output: " + solution.longestPalindrome(s2)); -2. The program uses an integer array `dp` of the same length as `newStr` to store information about the lengths of palindromes centered at different positions. The space complexity of `dp` is also O(n). + String s3 = "a"; + System.out.println("Example 3 Output: " + solution.longestPalindrome(s3)); -3. The program uses several integer variables (`friendCenter`, `friendRadius`, `lpsCenter`, and `lpsRadius`) to keep track of information during the algorithm. These variables take up constant space. + String s4 = "ac"; + System.out.println("Example 4 Output: " + solution.longestPalindrome(s4)); + } +} +``` -Therefore, the overall space complexity is dominated by the space used for `newStr` and `dp`, both of which are O(n). +This implementation provides a solution to the Longest Palindromic Substring problem in Java. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0006_zigzag_conversion/readme.md b/src/main/java/g0001_0100/s0006_zigzag_conversion/readme.md index 3fd689d1..ca399dab 100644 --- a/src/main/java/g0001_0100/s0006_zigzag_conversion/readme.md +++ b/src/main/java/g0001_0100/s0006_zigzag_conversion/readme.md @@ -41,37 +41,70 @@ string convert(string s, int numRows); * `s` consists of English letters (lower-case and upper-case), `','` and `'.'`. * `1 <= numRows <= 1000` -## Solution +To solve the Zigzag Conversion problem in Java using a `Solution` class, we'll follow these steps: + +1. Define a `Solution` class with a method named `convert`. +2. Create an array of strings to represent each row of the zigzag pattern. +3. Initialize variables to keep track of the current row (`row`) and the direction of traversal (`down`). +4. Iterate through each character in the input string `s`. + - Append the current character to the string representing the current row. + - If we reach the first or last row, change the direction of traversal accordingly. + - Update the current row based on the direction of traversal. +5. Concatenate the strings representing each row to form the final zigzag conversion. +6. Return the concatenated string. +7. Handle edge cases where the number of rows is 1 or the input string is empty. + +Here's the implementation: ```java public class Solution { + public String convert(String s, int numRows) { - int sLen = s.length(); - if (numRows == 1) { + if (numRows == 1 || s.length() <= numRows) { return s; } - int maxDist = numRows * 2 - 2; - StringBuilder buf = new StringBuilder(); + + StringBuilder[] rows = new StringBuilder[numRows]; for (int i = 0; i < numRows; i++) { - int index = i; - if (i == 0 || i == numRows - 1) { - while (index < sLen) { - buf.append(s.charAt(index)); - index += maxDist; - } - } else { - while (index < sLen) { - buf.append(s.charAt(index)); - index += maxDist - i * 2; - if (index >= sLen) { - break; - } - buf.append(s.charAt(index)); - index += i * 2; - } + rows[i] = new StringBuilder(); + } + + int row = 0; + boolean down = false; + + for (char c : s.toCharArray()) { + rows[row].append(c); + if (row == 0 || row == numRows - 1) { + down = !down; } + row += down ? 1 : -1; + } + + StringBuilder result = new StringBuilder(); + for (StringBuilder sb : rows) { + result.append(sb); } - return buf.toString(); + + return result.toString(); + } + + public static void main(String[] args) { + Solution solution = new Solution(); + + // Test cases + String s1 = "PAYPALISHIRING"; + int numRows1 = 3; + System.out.println("Example 1 Output: " + solution.convert(s1, numRows1)); + + String s2 = "PAYPALISHIRING"; + int numRows2 = 4; + System.out.println("Example 2 Output: " + solution.convert(s2, numRows2)); + + String s3 = "A"; + int numRows3 = 1; + System.out.println("Example 3 Output: " + solution.convert(s3, numRows3)); } } -``` \ No newline at end of file +``` + +This implementation provides a solution to the Zigzag Conversion problem in Java. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0007_reverse_integer/readme.md b/src/main/java/g0001_0100/s0007_reverse_integer/readme.md index 8a549b0e..5375580c 100644 --- a/src/main/java/g0001_0100/s0007_reverse_integer/readme.md +++ b/src/main/java/g0001_0100/s0007_reverse_integer/readme.md @@ -37,20 +37,63 @@ Given a signed 32-bit integer `x`, return `x` _with its digits reversed_. If rev * -231 <= x <= 231 - 1 -## Solution +To solve the Reverse Integer problem in Java using a `Solution` class, we'll follow these steps: + +1. Define a `Solution` class with a method named `reverse`. +2. Initialize variables to keep track of the reversed integer (`rev`), the sign of the input integer (`sign`), and the absolute value of the input integer (`x`). +3. Iterate through each digit of the input integer `x`: + - Extract the least significant digit using the modulo operator. + - Update the reversed integer `rev` by multiplying it by 10 and adding the extracted digit. + - Update `x` by removing the least significant digit using integer division. +4. Check if the reversed integer `rev` overflows the signed 32-bit integer range. If so, return 0. +5. Return the reversed integer `rev` with the appropriate sign. + +Here's the implementation: ```java public class Solution { + public int reverse(int x) { - long rev = 0; - while (x != 0) { - rev = (rev * 10) + (x % 10); - x /= 10; - } - if (rev > Integer.MAX_VALUE || rev < Integer.MIN_VALUE) { - return 0; + int rev = 0; + int sign = (x < 0) ? -1 : 1; + int limit = Integer.MAX_VALUE / 10; + int absX = Math.abs(x); + + while (absX > 0) { + int digit = absX % 10; + absX /= 10; + + if (rev > limit || (rev == limit && digit > 7)) { + return 0; + } + + if (rev < -limit || (rev == -limit && digit < -8)) { + return 0; + } + + rev = rev * 10 + digit; } - return (int) rev; + + return rev * sign; + } + + public static void main(String[] args) { + Solution solution = new Solution(); + + // Test cases + int x1 = 123; + System.out.println("Example 1 Output: " + solution.reverse(x1)); + + int x2 = -123; + System.out.println("Example 2 Output: " + solution.reverse(x2)); + + int x3 = 120; + System.out.println("Example 3 Output: " + solution.reverse(x3)); + + int x4 = 0; + System.out.println("Example 4 Output: " + solution.reverse(x4)); } } -``` \ No newline at end of file +``` + +This implementation provides a solution to the Reverse Integer problem in Java. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0008_string_to_integer_atoi/readme.md b/src/main/java/g0001_0100/s0008_string_to_integer_atoi/readme.md index 36419930..67a3f8f2 100644 --- a/src/main/java/g0001_0100/s0008_string_to_integer_atoi/readme.md +++ b/src/main/java/g0001_0100/s0008_string_to_integer_atoi/readme.md @@ -115,46 +115,73 @@ Since -91283472332 is less than the lower bound of the range [-231, 2 * `0 <= s.length <= 200` * `s` consists of English letters (lower-case and upper-case), digits (`0-9`), `' '`, `'+'`, `'-'`, and `'.'`. -## Solution +To solve the String to Integer (atoi) problem in Java using a `Solution` class, we'll follow these steps: + +1. Define a `Solution` class with a method named `myAtoi`. +2. Trim leading whitespace from the input string `s`. +3. Check if the string is empty after trimming. If so, return 0. +4. Initialize variables to keep track of the sign of the integer (`sign`), the starting index of the numeric characters (`start`), and the result (`result`). +5. Check if the first character of the trimmed string is `'-'` or `'+'`. Update `sign` accordingly, and move the starting index accordingly. +6. Iterate through the characters of the trimmed string starting from the `start` index: + - Check if the current character is a digit. If not, break the loop. + - Convert the character to its numeric value and update the `result`. + - Check if the result exceeds the 32-bit integer range. If so, clamp it to the range and return. +7. Multiply the `result` by the sign and return the final value. +8. Handle edge cases where the input string is empty, consists of only whitespace, or contains non-numeric characters at the beginning. + +Here's the implementation: ```java public class Solution { - public int myAtoi(String str) { - if (str == null || str.length() == 0) { - return 0; - } - int i = 0; - boolean negetiveSign = false; - char[] input = str.toCharArray(); - while (i < input.length && input[i] == ' ') { - i++; - } - if (i == input.length) { + + public int myAtoi(String s) { + s = s.trim(); + if (s.isEmpty()) return 0; - } else if (input[i] == '+') { - i++; - } else if (input[i] == '-') { - i++; - negetiveSign = true; + + int sign = 1; + int start = 0; + long result = 0; + + if (s.charAt(0) == '-' || s.charAt(0) == '+') { + sign = (s.charAt(0) == '-') ? -1 : 1; + start++; } - int num = 0; - while (i < input.length && input[i] <= '9' && input[i] >= '0') { - // current char - int tem = input[i] - '0'; - tem = negetiveSign ? -tem : tem; - // avoid invalid number like 038 - if (num == 0 && tem == '0') { - i++; - } else if (num == Integer.MIN_VALUE / 10 && tem <= -8 || num < Integer.MIN_VALUE / 10) { - return Integer.MIN_VALUE; - } else if (num == Integer.MAX_VALUE / 10 && tem >= 7 || num > Integer.MAX_VALUE / 10) { + + for (int i = start; i < s.length(); i++) { + char c = s.charAt(i); + if (!Character.isDigit(c)) + break; + result = result * 10 + (c - '0'); + if (result * sign > Integer.MAX_VALUE) return Integer.MAX_VALUE; - } else { - num = num * 10 + tem; - i++; - } + if (result * sign < Integer.MIN_VALUE) + return Integer.MIN_VALUE; } - return num; + + return (int) (result * sign); + } + + public static void main(String[] args) { + Solution solution = new Solution(); + + // Test cases + String s1 = "42"; + System.out.println("Example 1 Output: " + solution.myAtoi(s1)); + + String s2 = " -42"; + System.out.println("Example 2 Output: " + solution.myAtoi(s2)); + + String s3 = "4193 with words"; + System.out.println("Example 3 Output: " + solution.myAtoi(s3)); + + String s4 = "words and 987"; + System.out.println("Example 4 Output: " + solution.myAtoi(s4)); + + String s5 = "-91283472332"; + System.out.println("Example 5 Output: " + solution.myAtoi(s5)); } } -``` \ No newline at end of file +``` + +This implementation provides a solution to the String to Integer (atoi) problem in Java. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0009_palindrome_number/readme.md b/src/main/java/g0001_0100/s0009_palindrome_number/readme.md index cefe3544..bd9418fd 100644 --- a/src/main/java/g0001_0100/s0009_palindrome_number/readme.md +++ b/src/main/java/g0001_0100/s0009_palindrome_number/readme.md @@ -43,22 +43,61 @@ An integer is a **palindrome** when it reads the same backward as forward. For e **Follow up:** Could you solve it without converting the integer to a string? -## Solution +To solve the Palindrome Number problem in Java using a `Solution` class, we'll follow these steps: + +1. Define a `Solution` class with a method named `isPalindrome`. +2. Handle special cases where `x` is negative or divisible by 10 but not equal to zero, as they cannot be palindromes. +3. Initialize variables to keep track of the reversed number (`reversed`) and the original number (`original`). +4. Iterate through the digits of the original number `x`: + - Extract the least significant digit using the modulo operator and append it to the reversed number. + - Update `original` by removing the least significant digit using integer division. +5. Check if the reversed number is equal to the original number. If so, return `true`; otherwise, return `false`. + +Here's the implementation: ```java public class Solution { + public boolean isPalindrome(int x) { - if (x < 0) { + // Special cases: + // As discussed, negative numbers are not palindromes. + // Also, if the last digit of the number is 0, it can't be a palindrome unless the number is 0 itself. + if (x < 0 || (x % 10 == 0 && x != 0)) { return false; } - int rev = 0; - int localX = x; - while (localX > 0) { - rev *= 10; - rev += localX % 10; - localX /= 10; + + int reversed = 0; + int original = x; + + while (original > reversed) { + int digit = original % 10; + reversed = reversed * 10 + digit; + original /= 10; } - return rev == x; + + // When the length is an odd number, we can get rid of the middle digit by reversed / 10 + // For example when the input is 12321, at the end of the while loop we get x = 12, reversed = 123, + // since the middle digit doesn't matter in palidrome(it will always equal to itself), we can simply get rid of it. + return original == reversed || original == reversed / 10; + } + + public static void main(String[] args) { + Solution solution = new Solution(); + + // Test cases + int x1 = 121; + System.out.println("Example 1 Output: " + solution.isPalindrome(x1)); + + int x2 = -121; + System.out.println("Example 2 Output: " + solution.isPalindrome(x2)); + + int x3 = 10; + System.out.println("Example 3 Output: " + solution.isPalindrome(x3)); + + int x4 = -101; + System.out.println("Example 4 Output: " + solution.isPalindrome(x4)); } } -``` \ No newline at end of file +``` + +This implementation provides a solution to the Palindrome Number problem in Java. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0010_regular_expression_matching/readme.md b/src/main/java/g0001_0100/s0010_regular_expression_matching/readme.md index 27d6d9c6..d293fb5d 100644 --- a/src/main/java/g0001_0100/s0010_regular_expression_matching/readme.md +++ b/src/main/java/g0001_0100/s0010_regular_expression_matching/readme.md @@ -58,53 +58,65 @@ The matching should cover the **entire** input string (not partial). * `p` contains only lowercase English letters, `'.'`, and `'*'`. * It is guaranteed for each appearance of the character `'*'`, there will be a previous valid character to match. -## Solution +To solve the Regular Expression Matching problem in Java using a `Solution` class, we'll follow these steps: + +1. Define a `Solution` class with a method named `isMatch`. +2. Implement a recursive approach to check for pattern matching. +3. Base cases: + - If the pattern string is empty, return `s.isEmpty()`. + - If the pattern string's length is 1 or the next character after `*` is `.`: + - Check if the length of `s` is 1 and the characters match or the pattern is `.`. + - If so, return `true`; otherwise, return `false`. +4. If the second character of the pattern is not `*`, recursively call `isMatch` with the substring starting from the second character. +5. If the second character of the pattern is `*`, recursively check all possibilities: + - Zero occurrences of the preceding character (skipping `*` and the character before it). + - One or more occurrences of the preceding character (matching the first character and recursively calling `isMatch` for the remaining part of the string). +6. Return the result of the recursive checks. +7. Handle edge cases where the input strings are empty or the pattern contains invalid characters. + +Here's the implementation: ```java public class Solution { - private Boolean[][] cache; public boolean isMatch(String s, String p) { - cache = new Boolean[s.length() + 1][p.length() + 1]; - return isMatch(s, p, 0, 0); - } + if (p.isEmpty()) + return s.isEmpty(); - private boolean isMatch(String s, String p, int i, int j) { - if (j == p.length()) { - return i == s.length(); - } - boolean result; - if (cache[i][j] != null) { - return cache[i][j]; - } - boolean firstMatch = i < s.length() && (s.charAt(i) == p.charAt(j) || p.charAt(j) == '.'); - if ((j + 1) < p.length() && p.charAt(j + 1) == '*') { - result = (firstMatch && isMatch(s, p, i + 1, j)) || isMatch(s, p, i, j + 2); + boolean firstMatch = !s.isEmpty() && (p.charAt(0) == s.charAt(0) || p.charAt(0) == '.'); + + if (p.length() >= 2 && p.charAt(1) == '*') { + return isMatch(s, p.substring(2)) || (firstMatch && isMatch(s.substring(1), p)); } else { - result = firstMatch && isMatch(s, p, i + 1, j + 1); + return firstMatch && isMatch(s.substring(1), p.substring(1)); } - cache[i][j] = result; - return result; } -} -``` -**Time Complexity (Big O Time):** + public static void main(String[] args) { + Solution solution = new Solution(); -The time complexity of this program is O(m*n), where "m" represents the length of the string `s`, and "n" represents the length of the string `p`. Here's the breakdown: + // Test cases + String s1 = "aa"; + String p1 = "a"; + System.out.println("Example 1 Output: " + solution.isMatch(s1, p1)); -1. The `cache` is a 2D Boolean array with dimensions (s.length() + 1) x (p.length() + 1). Therefore, it has O(m*n) space complexity. + String s2 = "aa"; + String p2 = "a*"; + System.out.println("Example 2 Output: " + solution.isMatch(s2, p2)); -2. The program uses dynamic programming and recursion to determine if the given strings `s` and `p` match. The primary function `isMatch` is called with varying indices `i` and `j` within the ranges [0, m] and [0, n], respectively. + String s3 = "ab"; + String p3 = ".*"; + System.out.println("Example 3 Output: " + solution.isMatch(s3, p3)); -3. The `cache` array is used to memoize the results of subproblems to avoid redundant computations. If the result for a specific `(i, j)` pair is already in the cache, it's retrieved in constant time. + String s4 = "aab"; + String p4 = "c*a*b"; + System.out.println("Example 4 Output: " + solution.isMatch(s4, p4)); -4. The recursion, however, explores all possible combinations of `i` and `j` values. In the worst case, it explores all possible pairs within the range [0, m] and [0, n], resulting in a time complexity of O(m*n). - -Therefore, the overall time complexity is O(m*n). - -**Space Complexity (Big O Space):** - -The space complexity of this program is O(m*n), primarily due to the `cache` 2D Boolean array. Additionally, there's a negligible amount of space used for other variables, such as `result`, `firstMatch`, `i`, and `j`, which are all constants and do not depend on the input size. + String s5 = "mississippi"; + String p5 = "mis*is*p*."; + System.out.println("Example 5 Output: " + solution.isMatch(s5, p5)); + } +} +``` -Hence, the dominant factor in terms of space complexity is the `cache` array, which has O(m*n) space complexity. +This implementation provides a solution to the Regular Expression Matching problem in Java. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0011_container_with_most_water/readme.md b/src/main/java/g0001_0100/s0011_container_with_most_water/readme.md index 1b31cc44..f045e24d 100644 --- a/src/main/java/g0001_0100/s0011_container_with_most_water/readme.md +++ b/src/main/java/g0001_0100/s0011_container_with_most_water/readme.md @@ -43,42 +43,58 @@ Given `n` non-negative integers a1, a2, ..., an * 2 <= n <= 105 * 0 <= height[i] <= 104 -## Solution +To solve the Container With Most Water problem in Java using a `Solution` class, we'll follow these steps: + +1. Define a `Solution` class with a method named `maxArea` that takes an array of integers `height` as input and returns the maximum area of water that can be contained. +2. Initialize two pointers, `left` pointing to the start of the array and `right` pointing to the end of the array. +3. Initialize a variable `maxArea` to store the maximum area encountered so far, initially set to 0. +4. Iterate while `left` is less than `right`. +5. Calculate the current area using the formula: `(right - left) * min(height[left], height[right])`. +6. Update `maxArea` if the current area is greater than `maxArea`. +7. Move the pointer pointing to the smaller height towards the other pointer. If `height[left] < height[right]`, increment `left`, otherwise decrement `right`. +8. Continue the iteration until `left` becomes greater than or equal to `right`. +9. Return `maxArea`. + +Here's the implementation: ```java public class Solution { public int maxArea(int[] height) { - int maxArea = -1; int left = 0; int right = height.length - 1; + int maxArea = 0; + while (left < right) { + int currentArea = (right - left) * Math.min(height[left], height[right]); + maxArea = Math.max(maxArea, currentArea); + if (height[left] < height[right]) { - maxArea = Math.max(maxArea, height[left] * (right - left)); left++; } else { - maxArea = Math.max(maxArea, height[right] * (right - left)); right--; } } + return maxArea; } -} -``` - -**Time Complexity (Big O Time):** -The time complexity of this program is O(n), where "n" represents the number of elements in the `height` array. Here's the breakdown: + public static void main(String[] args) { + Solution solution = new Solution(); -1. The program uses a two-pointer approach with `left` and `right` pointers initialized at the beginning and end of the `height` array. -2. It iterates through the array using a `while` loop, and in each iteration, it performs constant-time operations: - - It calculates the area as the product of the heights at the current `left` and `right` pointers and the distance between them (constant time). - - It updates the `maxArea` variable by taking the maximum of the current `maxArea` and the calculated area (constant time). - - It moves either the `left` or `right` pointer toward the center of the array based on the condition `height[left] < height[right]` or `height[left] >= height[right]`. + // Test cases + int[] height1 = {1, 8, 6, 2, 5, 4, 8, 3, 7}; + System.out.println("Example 1 Output: " + solution.maxArea(height1)); -Since the `while` loop runs until the `left` and `right` pointers meet in the middle, and each iteration performs constant-time operations, the overall time complexity is O(n), where "n" is the number of elements in the `height` array. + int[] height2 = {1, 1}; + System.out.println("Example 2 Output: " + solution.maxArea(height2)); -**Space Complexity (Big O Space):** + int[] height3 = {4, 3, 2, 1, 4}; + System.out.println("Example 3 Output: " + solution.maxArea(height3)); -The space complexity of this program is O(1), which means it uses a constant amount of extra space that does not depend on the input size. The program uses only a few integer variables (`maxArea`, `left`, and `right`) to keep track of the maximum area and the positions of the two pointers. The space used by these variables remains constant regardless of the input size. + int[] height4 = {1, 2, 1}; + System.out.println("Example 4 Output: " + solution.maxArea(height4)); + } +} +``` -Therefore, the overall space complexity is O(1). +This implementation provides a solution to the Container With Most Water problem in Java. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0015_3sum/readme.md b/src/main/java/g0001_0100/s0015_3sum/readme.md index b90a7a9e..288da4a8 100644 --- a/src/main/java/g0001_0100/s0015_3sum/readme.md +++ b/src/main/java/g0001_0100/s0015_3sum/readme.md @@ -32,77 +32,81 @@ Notice that the solution set must not contain duplicate triplets. * `0 <= nums.length <= 3000` * -105 <= nums[i] <= 105 -## Solution +To solve the 3Sum problem in Java using a `Solution` class, we'll follow these steps: + +1. Define a `Solution` class with a method named `threeSum` that takes an array of integers `nums` as input and returns a list of lists representing the triplets that sum up to zero. +2. Sort the input array `nums` to ensure that duplicate triplets are avoided. +3. Initialize an empty list `result` to store the triplets. +4. Iterate over the elements of the sorted array `nums` up to the second to last element. +5. Within the outer loop, initialize two pointers, `left` and `right`, where `left` starts at the next element after the current element and `right` starts at the last element of the array. +6. While `left` is less than `right`, check if the sum of the current element (`nums[i]`), `nums[left]`, and `nums[right]` equals zero. +7. If the sum is zero, add `[nums[i], nums[left], nums[right]]` to the `result` list. +8. Move the `left` pointer to the right (increment `left`) and the `right` pointer to the left (decrement `right`). +9. If the sum is less than zero, increment `left`. +10. If the sum is greater than zero, decrement `right`. +11. After the inner loop finishes, increment the outer loop index while skipping duplicates. +12. Return the `result` list containing all the valid triplets. + +Here's the implementation: ```java import java.util.ArrayList; import java.util.Arrays; import java.util.List; -@SuppressWarnings("java:S127") public class Solution { public List> threeSum(int[] nums) { Arrays.sort(nums); - final int len = nums.length; List> result = new ArrayList<>(); - int l; - int r; - for (int i = 0; i < len - 2; i++) { - l = i + 1; - r = len - 1; - while (r > l) { - int sum = nums[i] + nums[l] + nums[r]; - if (sum < 0) { - l++; - } else if (sum > 0) { - r--; - } else { - List list = new ArrayList<>(); - list.add(nums[i]); - list.add(nums[l]); - list.add(nums[r]); - result.add(list); - while (l < r && nums[l + 1] == nums[l]) { - l++; + + for (int i = 0; i < nums.length - 2; i++) { + if (i > 0 && nums[i] == nums[i - 1]) { + continue; // Skip duplicates + } + + int left = i + 1; + int right = nums.length - 1; + + while (left < right) { + int sum = nums[i] + nums[left] + nums[right]; + if (sum == 0) { + result.add(Arrays.asList(nums[i], nums[left], nums[right])); + + // Skip duplicates + while (left < right && nums[left] == nums[left + 1]) { + left++; } - while (r > l && nums[r - 1] == nums[r]) { - r--; + while (left < right && nums[right] == nums[right - 1]) { + right--; } - l++; - r--; + + left++; + right--; + } else if (sum < 0) { + left++; + } else { + right--; } } - while (i < len - 1 && nums[i + 1] == nums[i]) { - i++; - } } + return result; } -} -``` -**Time Complexity (Big O Time):** + public static void main(String[] args) { + Solution solution = new Solution(); -1. Sorting: The program sorts the input array `nums`. Sorting typically takes O(n * log(n)) time complexity, where 'n' is the length of the array. + // Test cases + int[] nums1 = {-1, 0, 1, 2, -1, -4}; + System.out.println("Example 1 Output: " + solution.threeSum(nums1)); -2. Main Loop: The program uses nested loops. The outer loop runs from 0 to `len - 2`, where `len` is the length of the sorted array `nums`. The inner while loop has two pointers (`l` and `r`) that move towards each other. In the worst case, the inner loop can go through the entire array, so its time complexity is O(n). + int[] nums2 = {}; + System.out.println("Example 2 Output: " + solution.threeSum(nums2)); -3. The code inside the inner loop contains constant-time operations, such as addition, comparison, and list creation. - -Overall, the dominant time complexity is determined by the sorting step, which is O(n * log(n)). The loop inside the sorting step has a complexity of O(n), but it doesn't dominate the overall complexity. - -So, the total time complexity of the program is O(n * log(n)) due to the sorting step. - -**Space Complexity (Big O Space):** - -The space complexity of the program is determined by the space used for the output list `result`. In the worst case, when there are many unique triplets that sum to zero, the size of `result` can be significant. - -1. The input array `nums` and the variables `len`, `l`, and `r` all use constant space. - -2. The `result` list stores the triplets, and its size can be at most O(n^2) when there are many unique triplets. - -3. Other variables and temporary lists used inside the loops use constant space. - -So, the space complexity of the program is O(n^2) for the `result` list when considering the worst case. + int[] nums3 = {0}; + System.out.println("Example 3 Output: " + solution.threeSum(nums3)); + } +} +``` -In summary, the provided program has a time complexity of O(n * log(n)) due to sorting and a space complexity of O(n^2) for the `result` list when considering the worst-case scenario. +This implementation provides a solution to the 3Sum problem in Java. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0017_letter_combinations_of_a_phone_number/readme.md b/src/main/java/g0001_0100/s0017_letter_combinations_of_a_phone_number/readme.md index 9d7c2931..0d50b161 100644 --- a/src/main/java/g0001_0100/s0017_letter_combinations_of_a_phone_number/readme.md +++ b/src/main/java/g0001_0100/s0017_letter_combinations_of_a_phone_number/readme.md @@ -34,64 +34,75 @@ A mapping of digit to letters (just like on the telephone buttons) is given belo * `0 <= digits.length <= 4` * `digits[i]` is a digit in the range `['2', '9']`. -## Solution +To solve the Letter Combinations of a Phone Number problem in Java using a `Solution` class, we'll follow these steps: + +1. Define a `Solution` class with a method named `letterCombinations` that takes a string `digits` as input and returns a list of all possible letter combinations. +2. Create a mapping of digits to letters using a hashmap or an array. +3. Initialize an empty list `result` to store the combinations. +4. If the input string `digits` is empty, return an empty list `result`. +5. Call a recursive function `generateCombinations` to generate combinations for each digit. +6. Within the recursive function: + - Base case: If the current combination length equals the length of the input `digits`, add the combination to the `result` list. + - Recursive step: For the current digit, iterate over its corresponding letters and append each letter to the current combination, then recursively call the function with the next digit. +7. Return the `result` list containing all possible combinations. + +Here's the implementation: ```java import java.util.ArrayList; -import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; public class Solution { + private static final Map digitToLetters = new HashMap<>(); + static { + digitToLetters.put('2', "abc"); + digitToLetters.put('3', "def"); + digitToLetters.put('4', "ghi"); + digitToLetters.put('5', "jkl"); + digitToLetters.put('6', "mno"); + digitToLetters.put('7', "pqrs"); + digitToLetters.put('8', "tuv"); + digitToLetters.put('9', "wxyz"); + } + public List letterCombinations(String digits) { - if (digits.isEmpty()) { - return Collections.emptyList(); + List result = new ArrayList<>(); + if (digits.length() == 0) { + return result; } - String[] letters = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; - List ans = new ArrayList<>(); - StringBuilder sb = new StringBuilder(); - findCombinations(0, digits, letters, sb, ans); - return ans; + generateCombinations(result, digits, "", 0); + return result; } - private void findCombinations( - int start, String nums, String[] letters, StringBuilder curr, List ans) { - if (curr.length() == nums.length()) { - ans.add(curr.toString()); + private void generateCombinations(List result, String digits, String combination, int index) { + if (index == digits.length()) { + result.add(combination); return; } - for (int i = start; i < nums.length(); i++) { - int n = Character.getNumericValue(nums.charAt(i)); - for (int j = 0; j < letters[n].length(); j++) { - char ch = letters[n].charAt(j); - curr.append(ch); - findCombinations(i + 1, nums, letters, curr, ans); - curr.deleteCharAt(curr.length() - 1); - } + + char digit = digits.charAt(index); + String letters = digitToLetters.get(digit); + for (char letter : letters.toCharArray()) { + generateCombinations(result, digits, combination + letter, index + 1); } } -} -``` - -**Time Complexity (Big O Time):** - -The time complexity of this program is O(4^n), where "n" is the number of digits in the input string `digits`. Here's the breakdown: -1. The program uses a recursive approach to generate all possible letter combinations for the input digits. + public static void main(String[] args) { + Solution solution = new Solution(); -2. The `findCombinations` method is called recursively for each digit in the input string `digits`. For each digit, it generates multiple combinations by iterating through the corresponding letters (e.g., "abc" for digit 2). + // Test cases + String digits1 = "23"; + System.out.println("Example 1 Output: " + solution.letterCombinations(digits1)); -3. The number of recursive calls made by the program is exponential in nature. For each digit, there are typically 3 or 4 letters associated with it (except for "0" and "1" with no associated letters). Therefore, in the worst case, the number of recursive calls per digit can be considered constant. + String digits2 = ""; + System.out.println("Example 2 Output: " + solution.letterCombinations(digits2)); -4. Since there are "n" digits in the input string, and for each digit, there are a constant number of recursive calls (3 or 4), the overall time complexity is exponential, specifically O(4^n). - -**Space Complexity (Big O Space):** - -The space complexity of this program is O(n), where "n" is the number of digits in the input string `digits`. Here's why: - -1. The program uses a `StringBuilder` (`curr`) to build the current combination of letters. The maximum length of this `StringBuilder` is equal to the number of digits in the input string `digits`. - -2. The program uses a list (`ans`) to store the final letter combinations, but the space used by this list is proportional to the number of valid combinations, which is less than or equal to 4^n. - -3. Other than the `curr` and `ans` variables, the program uses a few integer variables and arrays (e.g., `start`, `nums`, `letters`) with constant space requirements. + String digits3 = "2"; + System.out.println("Example 3 Output: " + solution.letterCombinations(digits3)); + } +} +``` -Therefore, the overall space complexity is O(n), primarily due to the `curr` `StringBuilder` and the list `ans`. +This implementation provides a solution to the Letter Combinations of a Phone Number problem in Java. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0019_remove_nth_node_from_end_of_list/readme.md b/src/main/java/g0001_0100/s0019_remove_nth_node_from_end_of_list/readme.md index c223a6a9..bd38a472 100644 --- a/src/main/java/g0001_0100/s0019_remove_nth_node_from_end_of_list/readme.md +++ b/src/main/java/g0001_0100/s0019_remove_nth_node_from_end_of_list/readme.md @@ -36,65 +36,93 @@ Given the `head` of a linked list, remove the `nth` node from the end of the lis **Follow up:** Could you do this in one pass? -## Solution +To solve the Remove Nth Node From End of List problem in Java with a `Solution` class, we'll follow these steps: + +1. Define a `ListNode` class representing the nodes of the linked list. +2. Define a `Solution` class with a method named `removeNthFromEnd` that takes the head of the linked list and an integer `n` as input and returns the head of the modified list. +3. Create two pointers, `fast` and `slow`, and initialize them to point to the head of the list. +4. Move the `fast` pointer `n` steps forward in the list. +5. If the `fast` pointer reaches the end of the list (`fast == null`), it means that `n` is equal to the length of the list. In this case, remove the head node by returning `head.next`. +6. Move both `fast` and `slow` pointers simultaneously until the `fast` pointer reaches the end of the list. +7. At this point, the `slow` pointer will be pointing to the node just before the node to be removed. +8. Remove the `nth` node by updating the `next` reference of the node pointed to by the `slow` pointer to skip the `nth` node. +9. Return the head of the modified list. + +Here's the implementation: ```java -import com_github_leetcode.ListNode; - -/* - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode() {} - * ListNode(int val) { this.val = val; } - * ListNode(int val, ListNode next) { this.val = val; this.next = next; } - * } - */ -public class Solution { - private int n; +public class ListNode { + int val; + ListNode next; + ListNode(int val) { this.val = val; } +} +public class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { - this.n = n; - ListNode node = new ListNode(0, head); - removeNth(node); - return node.next; + ListNode dummy = new ListNode(0); + dummy.next = head; + ListNode fast = dummy; + ListNode slow = dummy; + + // Move the fast pointer n steps forward + for (int i = 0; i <= n; i++) { + fast = fast.next; + } + + // Move both pointers until the fast pointer reaches the end + while (fast != null) { + fast = fast.next; + slow = slow.next; + } + + // Remove the nth node + slow.next = slow.next.next; + + return dummy.next; + } + + public static void main(String[] args) { + Solution solution = new Solution(); + + // Example 1 + ListNode head1 = new ListNode(1); + head1.next = new ListNode(2); + head1.next.next = new ListNode(3); + head1.next.next.next = new ListNode(4); + head1.next.next.next.next = new ListNode(5); + int n1 = 2; + ListNode result1 = solution.removeNthFromEnd(head1, n1); + printList(result1); // Output: [1,2,3,5] + + // Example 2 + ListNode head2 = new ListNode(1); + int n2 = 1; + ListNode result2 = solution.removeNthFromEnd(head2, n2); + printList(result2); // Output: [] + + // Example 3 + ListNode head3 = new ListNode(1); + head3.next = new ListNode(2); + int n3 = 1; + ListNode result3 = solution.removeNthFromEnd(head3, n3); + printList(result3); // Output: [1] } - private void removeNth(ListNode node) { - if (node.next == null) { + private static void printList(ListNode head) { + if (head == null) { + System.out.println("[]"); return; } - removeNth(node.next); - this.n--; - - if (this.n == 0) { - node.next = node.next.next; + StringBuilder sb = new StringBuilder("["); + while (head != null) { + sb.append(head.val).append(","); + head = head.next; } + sb.setLength(sb.length() - 1); + sb.append("]"); + System.out.println(sb.toString()); } } ``` -**Time Complexity (Big O Time):** - -The time complexity of this program is O(L), where "L" is the length of the input linked list `head`. Here's the breakdown: - -1. The program uses a recursive approach to remove the nth node from the end of the linked list. - -2. The `removeNthFromEnd` method is called recursively for each node in the linked list. The recursive calls traverse the entire list once, visiting each node exactly once. - -3. Since the recursive calls traverse the entire list, the total number of operations performed is proportional to the length of the linked list `head`, which is "L." - -Therefore, the overall time complexity is O(L), where "L" is the length of the linked list. - -**Space Complexity (Big O Space):** - -The space complexity of this program is O(L), where "L" is the length of the input linked list `head`. Here's why: - -1. The program uses a recursive approach, and for each recursive call, it adds a new frame to the call stack. In the worst case, when the linked list is traversed from beginning to end, there can be a maximum of "L" recursive calls on the stack at once. - -2. Each recursive call stores local variables and a reference to the next recursive call. The space used by each call frame is constant, but the number of frames on the stack is proportional to the length of the linked list. - -3. Additionally, the program uses a few integer variables and references to linked list nodes, but these use constant space relative to the input size. - -Therefore, the overall space complexity is O(L), where "L" is the length of the linked list. +This implementation provides a solution to the Remove Nth Node From End of List problem in Java. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0020_valid_parentheses/readme.md b/src/main/java/g0001_0100/s0020_valid_parentheses/readme.md index 594e2a6a..04fc0586 100644 --- a/src/main/java/g0001_0100/s0020_valid_parentheses/readme.md +++ b/src/main/java/g0001_0100/s0020_valid_parentheses/readme.md @@ -47,54 +47,54 @@ An input string is valid if: * 1 <= s.length <= 104 * `s` consists of parentheses only `'()[]{}'`. -## Solution +To solve the Valid Parentheses problem in Java with a `Solution` class, we'll use a stack data structure. Here are the steps: + +1. Define a `Solution` class with a method named `isValid` that takes a string `s` as input and returns a boolean indicating whether the string contains valid parentheses. +2. Create a stack to store opening parentheses. +3. Iterate through each character in the input string `s`. +4. If the current character is an opening parenthesis (`'('`, `'{'`, or `'['`), push it onto the stack. +5. If the current character is a closing parenthesis (`')'`, `'}'`, or `']'`), check if the stack is empty. If it is, return `false` because there's no matching opening parenthesis for the current closing parenthesis. +6. If the stack is not empty, pop the top element from the stack and check if it matches the current closing parenthesis. If it doesn't match, return `false`. +7. After iterating through all characters in `s`, check if the stack is empty. If it's not empty, return `false` because there are unmatched opening parentheses remaining. +8. If the stack is empty after processing all characters, return `true` because all parentheses are valid. + +Here's the implementation: ```java import java.util.Stack; -@SuppressWarnings("java:S1149") public class Solution { public boolean isValid(String s) { Stack stack = new Stack<>(); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - if (c == '(' || c == '[' || c == '{') { + + for (char c : s.toCharArray()) { + if (c == '(' || c == '{' || c == '[') { stack.push(c); - } else if (c == ')' && !stack.isEmpty() && stack.peek() == '(') { - stack.pop(); - } else if (c == '}' && !stack.isEmpty() && stack.peek() == '{') { - stack.pop(); - } else if (c == ']' && !stack.isEmpty() && stack.peek() == '[') { - stack.pop(); } else { - return false; + if (stack.isEmpty()) { + return false; + } + char top = stack.pop(); + if ((c == ')' && top != '(') || (c == '}' && top != '{') || (c == ']' && top != '[')) { + return false; + } } } + return stack.isEmpty(); } -} -``` - -**Time Complexity (Big O Time):** - -The time complexity of this program is O(n), where "n" represents the length of the input string `s`. Here's the breakdown: - -1. The program iterates through each character of the input string `s` using a `for` loop. This loop runs for "n" iterations, where "n" is the length of the string. -2. Inside the loop, the program performs constant-time operations for each character: - - It checks if the character is one of the opening parentheses (`(`, `[`, or `{`) and pushes it onto the stack (constant time). - - It checks if the character is one of the closing parentheses (`)`, `]`, or `}`) and verifies if it matches the corresponding opening parenthesis on the top of the stack. If they match, it pops the opening parenthesis from the stack (constant time). + public static void main(String[] args) { + Solution solution = new Solution(); -3. If any character other than parentheses is encountered, the program returns `false` immediately, so the worst-case scenario is iterating through the entire string. - -Since the loop runs for "n" iterations, and all operations inside the loop are constant time, the overall time complexity is O(n). - -**Space Complexity (Big O Space):** - -The space complexity of this program is O(n), where "n" represents the length of the input string `s`. Here's why: - -1. The program uses a stack (`stack`) to keep track of the opening parentheses encountered while iterating through the string. In the worst case, when the input string contains only opening parentheses, the stack can grow to have a maximum of "n" elements, where "n" is the length of the input string. - -2. Other than the stack, the program uses a few integer variables and character variables (`c`) that consume constant space relative to the input size. + // Test cases + System.out.println(solution.isValid("()")); // true + System.out.println(solution.isValid("()[]{}")); // true + System.out.println(solution.isValid("(]")); // false + System.out.println(solution.isValid("([)]")); // false + System.out.println(solution.isValid("{[]}")); // true + } +} +``` -Therefore, the dominant factor in terms of space complexity is the stack, which has a space complexity of O(n). +This implementation provides a solution to the Valid Parentheses problem in Java using a stack data structure. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0021_merge_two_sorted_lists/readme.md b/src/main/java/g0001_0100/s0021_merge_two_sorted_lists/readme.md index f7e06f4e..d6e63fd0 100644 --- a/src/main/java/g0001_0100/s0021_merge_two_sorted_lists/readme.md +++ b/src/main/java/g0001_0100/s0021_merge_two_sorted_lists/readme.md @@ -33,54 +33,69 @@ Merge two sorted linked lists and return it as a **sorted** list. The list shoul * `-100 <= Node.val <= 100` * Both `l1` and `l2` are sorted in **non-decreasing** order. -## Solution +To solve the Merge Two Sorted Lists problem in Java with a `Solution` class, we'll implement a recursive approach. Here are the steps: + +1. Define a `ListNode` class to represent a node in the linked list. +2. Define a `Solution` class with a method named `mergeTwoLists` that takes two linked lists `l1` and `l2` as input and returns a merged sorted list. +3. The base case for the recursion is when either `l1` or `l2` is null. In this case, return the non-null list because it's already sorted. +4. Compare the values of the heads of `l1` and `l2`. Let `head` be the smaller value of the two heads. +5. Recursively call `mergeTwoLists` with the next node of the smaller head and the other list that remained unchanged. +6. Update the `next` pointer of the smaller head to point to the result of the recursive call. +7. Return the smaller head, which is the merged sorted list. + +Here's the implementation: ```java -import com_github_leetcode.ListNode; - -/* - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode() {} - * ListNode(int val) { this.val = val; } - * ListNode(int val, ListNode next) { this.val = val; this.next = next; } - * } - */ public class Solution { + static class ListNode { + int val; + ListNode next; + + ListNode(int val) { + this.val = val; + } + } + public ListNode mergeTwoLists(ListNode l1, ListNode l2) { - ListNode list = new ListNode(-1); - ListNode head = list; - while (l1 != null || l2 != null) { - if (l1 != null && l2 != null) { - if (l1.val <= l2.val) { - list.next = new ListNode(l1.val); - l1 = l1.next; - } else { - list.next = new ListNode(l2.val); - l2 = l2.next; - } - } else if (l1 != null) { - list.next = new ListNode(l1.val); - l1 = l1.next; - } else { - list.next = new ListNode(l2.val); - l2 = l2.next; - } - list = list.next; + if (l1 == null) { + return l2; + } + if (l2 == null) { + return l1; + } + + ListNode head; + if (l1.val < l2.val) { + head = l1; + head.next = mergeTwoLists(l1.next, l2); + } else { + head = l2; + head.next = mergeTwoLists(l1, l2.next); } - return head.next; + + return head; } -} -``` -**Time Complexity (Big O Time):** + public static void main(String[] args) { + Solution solution = new Solution(); -The time complexity of this program is O(m + n), where m and n are the lengths of the input linked lists `l1` and `l2`. This is because the program iterates through both lists once, and the time complexity of each iteration is linear in the size of the input lists. In each iteration, it compares the values of the current nodes from `l1` and `l2` and adds the smaller value to the merged list. The loop will run until both `l1` and `l2` reach the end of their respective lists. + // Test cases + ListNode l1 = new ListNode(1); + l1.next = new ListNode(2); + l1.next.next = new ListNode(4); -**Space Complexity (Big O Space):** + ListNode l2 = new ListNode(1); + l2.next = new ListNode(3); + l2.next.next = new ListNode(4); -The space complexity of this program is O(m + n), where m and n are the lengths of the input linked lists `l1` and `l2`. This space is mainly used for creating a new linked list that stores the merged result. In each iteration of the loop, a new node is created for the merged list, which consumes additional space. The space complexity is directly proportional to the size of the input lists because the merged list will have m + n nodes in the worst case. + ListNode mergedList = solution.mergeTwoLists(l1, l2); + while (mergedList != null) { + System.out.print(mergedList.val + " "); + mergedList = mergedList.next; + } + System.out.println(); // newline + } +} +``` -Overall, the time and space complexity of the provided Java program is O(m + n), where m and n are the lengths of the input linked lists `l1` and `l2`. +This implementation provides a solution to the Merge Two Sorted Lists problem in Java using a recursive approach. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0022_generate_parentheses/readme.md b/src/main/java/g0001_0100/s0022_generate_parentheses/readme.md index 82bae86d..9052d1ef 100644 --- a/src/main/java/g0001_0100/s0022_generate_parentheses/readme.md +++ b/src/main/java/g0001_0100/s0022_generate_parentheses/readme.md @@ -23,7 +23,19 @@ Given `n` pairs of parentheses, write a function to _generate all combinations o * `1 <= n <= 8` -## Solution +To solve the "Generate Parentheses" problem in Java with a `Solution` class, we can use a backtracking approach. Here are the steps: + +1. Define a `Solution` class. +2. Define a method named `generateParenthesis` that takes an integer `n` as input and returns a list of strings representing all combinations of well-formed parentheses. +3. Create an empty list to store the result. +4. Call the recursive helper function `generateParenthesisHelper` with the empty string `""`, counts of open and close parentheses set to `0`, the value of `n`, and the result list. +5. In the `generateParenthesisHelper` function: + - If the length of the current string is equal to `2 * n`, add it to the result list. + - If the count of open parentheses is less than `n`, append an open parenthesis to the current string and call the function recursively with increased open count. + - If the count of close parentheses is less than the count of open parentheses, append a close parenthesis to the current string and call the function recursively with increased close count. +6. Return the result list. + +Here's the implementation: ```java import java.util.ArrayList; @@ -31,37 +43,39 @@ import java.util.List; public class Solution { public List generateParenthesis(int n) { - StringBuilder sb = new StringBuilder(); - List ans = new ArrayList<>(); - return generate(sb, ans, n, n); + List result = new ArrayList<>(); + generateParenthesisHelper("", 0, 0, n, result); + return result; } - private List generate(StringBuilder sb, List str, int open, int close) { - if (open == 0 && close == 0) { - str.add(sb.toString()); - return str; + private void generateParenthesisHelper(String current, int open, int close, int n, List result) { + if (current.length() == 2 * n) { + result.add(current); + return; } - if (open > 0) { - sb.append('('); - generate(sb, str, open - 1, close); - sb.deleteCharAt(sb.length() - 1); + + if (open < n) { + generateParenthesisHelper(current + "(", open + 1, close, n, result); } - if (close > 0 && open < close) { - sb.append(')'); - generate(sb, str, open, close - 1); - sb.deleteCharAt(sb.length() - 1); + + if (close < open) { + generateParenthesisHelper(current + ")", open, close + 1, n, result); } - return str; } -} -``` - -**Time Complexity (Big O Time):** -The time complexity of this program can be described as O(2^n), where n is the input value. This is because, in the worst case, the program generates all possible combinations of parentheses for a given value of `n`. For each position, it can either add an open parenthesis '(' or a close parenthesis ')'. Since there are 2 choices (open or close) for each position, and there are a total of 2n positions, the total number of combinations is 2^(2n), which simplifies to O(2^n) in big O notation. + public static void main(String[] args) { + Solution solution = new Solution(); -**Space Complexity (Big O Space):** + // Test cases + int n1 = 3; + System.out.println("Parentheses combinations for n = " + n1 + ":"); + System.out.println(solution.generateParenthesis(n1)); -The space complexity of this program is O(n), where n is the input value. This space is used for storing the current combination of parentheses in the `StringBuilder` `sb` and also for storing the final list of valid combinations in the `List str`. In each recursive call to the `generate` method, a new character is appended to the `StringBuilder`, and the `StringBuilder` is modified. However, the space used for the `StringBuilder` is not accumulated across recursive calls because characters are added and removed. Therefore, the space complexity is mainly determined by the depth of the recursion, which is proportional to the value of `n`. + int n2 = 1; + System.out.println("\nParentheses combinations for n = " + n2 + ":"); + System.out.println(solution.generateParenthesis(n2)); + } +} +``` -In summary, the time complexity of the provided program is O(2^n), and the space complexity is O(n), where n is the input value representing the number of pairs of parentheses to generate. +This implementation provides a solution to the "Generate Parentheses" problem in Java using a backtracking approach. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0023_merge_k_sorted_lists/readme.md b/src/main/java/g0001_0100/s0023_merge_k_sorted_lists/readme.md index a20b5b33..961b9660 100644 --- a/src/main/java/g0001_0100/s0023_merge_k_sorted_lists/readme.md +++ b/src/main/java/g0001_0100/s0023_merge_k_sorted_lists/readme.md @@ -38,93 +38,99 @@ _Merge all the linked-lists into one sorted linked-list and return it._ * `lists[i]` is sorted in **ascending order**. * The sum of `lists[i].length` won't exceed `10^4`. -## Solution +To solve the "Merge k Sorted Lists" problem in Java with a `Solution` class, we can use a priority queue (min-heap) to efficiently merge the lists. Here are the steps: + +1. Define a `Solution` class. +2. Define a method named `mergeKLists` that takes an array of linked lists `lists` as input and returns a single sorted linked list. +3. Create a priority queue of ListNode objects. We will use this priority queue to store the heads of each linked list. +4. Iterate through each linked list in the input array `lists` and add the head node of each list to the priority queue. +5. Create a dummy ListNode object to serve as the head of the merged sorted linked list. +6. Initialize a ListNode object named `current` to point to the dummy node. +7. While the priority queue is not empty: + - Remove the ListNode with the smallest value from the priority queue. + - Add this node to the merged linked list by setting the `next` pointer of the `current` node to this node. + - Move the `current` pointer to the next node in the merged linked list. + - If the removed node has a `next` pointer, add the next node from the same list to the priority queue. +8. Return the `next` pointer of the dummy node, which points to the head of the merged sorted linked list. + +Here's the implementation: ```java -import com_github_leetcode.ListNode; - -/* - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode() {} - * ListNode(int val) { this.val = val; } - * ListNode(int val, ListNode next) { this.val = val; this.next = next; } - * } - */ +import java.util.PriorityQueue; + public class Solution { public ListNode mergeKLists(ListNode[] lists) { - if (lists.length == 0) { - return null; + PriorityQueue minHeap = new PriorityQueue<>((a, b) -> a.val - b.val); + + // Add the heads of all lists to the priority queue + for (ListNode node : lists) { + if (node != null) { + minHeap.offer(node); + } } - return mergeKLists(lists, 0, lists.length); - } - - private ListNode mergeKLists(ListNode[] lists, int leftIndex, int rightIndex) { - if (rightIndex > leftIndex + 1) { - int mid = (leftIndex + rightIndex) / 2; - ListNode left = mergeKLists(lists, leftIndex, mid); - ListNode right = mergeKLists(lists, mid, rightIndex); - return mergeTwoLists(left, right); - } else { - return lists[leftIndex]; + + // Create a dummy node to serve as the head of the merged list + ListNode dummy = new ListNode(0); + ListNode current = dummy; + + // Merge the lists + while (!minHeap.isEmpty()) { + ListNode minNode = minHeap.poll(); + current.next = minNode; + current = current.next; + + if (minNode.next != null) { + minHeap.offer(minNode.next); + } } + + return dummy.next; } - private ListNode mergeTwoLists(ListNode left, ListNode right) { - if (left == null) { - return right; - } - if (right == null) { - return left; - } - ListNode res; - if (left.val <= right.val) { - res = left; - left = left.next; - } else { - res = right; - right = right.next; - } - ListNode node = res; - while (left != null || right != null) { - if (left == null) { - node.next = right; - right = right.next; - } else if (right == null) { - node.next = left; - left = left.next; - } else { - if (left.val <= right.val) { - node.next = left; - left = left.next; - } else { - node.next = right; - right = right.next; - } - } - node = node.next; - } - return res; + public static void main(String[] args) { + Solution solution = new Solution(); + + // Test case + ListNode[] lists = new ListNode[] { + ListNode.createList(new int[] {1, 4, 5}), + ListNode.createList(new int[] {1, 3, 4}), + ListNode.createList(new int[] {2, 6}) + }; + System.out.println("Merged list:"); + ListNode.printList(solution.mergeKLists(lists)); } } -``` -**Time Complexity (Big O Time):** +class ListNode { + int val; + ListNode next; -1. The `mergeKLists` function is a recursive function that divides the problem into two subproblems of roughly half the size each time it's called. The recurrence relation for this function can be expressed as T(k) = 2T(k/2) + O(n), where k is the number of linked lists and n is the average number of nodes in each list. This recurrence relation represents the time complexity of the divide-and-conquer part of the algorithm. - -2. The `mergeTwoLists` function, which merges two sorted linked lists of size m and n, takes O(m + n) time. - -3. The `mergeKLists` function calls `mergeTwoLists` for merging two lists at each level of recursion. - -Combining these factors, the overall time complexity of the program is O(k * n * log(k)), where k is the number of linked lists, and n is the average number of nodes in each list. The logarithmic term arises from the divide-and-conquer approach, and the linear term comes from merging two lists at each level of recursion. + ListNode(int val) { + this.val = val; + } -**Space Complexity (Big O Space):** + static ListNode createList(int[] arr) { + if (arr == null || arr.length == 0) { + return null; + } -The space complexity of this program is O(log(k)) due to the recursive calls to `mergeKLists`. In each recursive call, a new set of recursive function calls and local variables is created, but they are released when the recursion unwinds. Therefore, the space required for the call stack is proportional to the depth of the recursion, which is log(k) in this case. + ListNode dummy = new ListNode(0); + ListNode current = dummy; + for (int num : arr) { + current.next = new ListNode(num); + current = current.next; + } + return dummy.next; + } -Additionally, the program uses a constant amount of space for other variables, such as `ListNode` objects for merging the lists and temporary variables for traversal. + static void printList(ListNode head) { + while (head != null) { + System.out.print(head.val + " "); + head = head.next; + } + System.out.println(); + } +} +``` -In summary, the time complexity of the provided program is O(k * n * log(k)), and the space complexity is O(log(k)), where k is the number of linked lists, and n is the average number of nodes in each list. +This implementation provides a solution to the "Merge k Sorted Lists" problem in Java using a priority queue. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0024_swap_nodes_in_pairs/readme.md b/src/main/java/g0001_0100/s0024_swap_nodes_in_pairs/readme.md index bd2d8412..dbca3cfe 100644 --- a/src/main/java/g0001_0100/s0024_swap_nodes_in_pairs/readme.md +++ b/src/main/java/g0001_0100/s0024_swap_nodes_in_pairs/readme.md @@ -32,73 +32,51 @@ Given a linked list, swap every two adjacent nodes and return its head. You must * The number of nodes in the list is in the range `[0, 100]`. * `0 <= Node.val <= 100` -## Solution +To solve the "Swap Nodes in Pairs" problem in Java with a `Solution` class, we can traverse the linked list while swapping pairs of nodes. Here are the steps: + +1. Define a `Solution` class. +2. Define a method named `swapPairs` that takes the head of a linked list as input and returns the head of the modified list. +3. Create a dummy ListNode object and set its `next` pointer to the head of the input list. This dummy node will serve as the new head of the modified list. +4. Initialize three pointers: `prev`, `first`, and `second`. +5. Iterate through the list while `first` and `second` are not null: + - Assign `first` to the `next` pointer of `prev`. + - Assign `second` to the `next` pointer of `first`. + - Assign the `next` pointer of `prev` to the `next` pointer of `second`. + - Assign the `next` pointer of `second` to `first`. + - Move `prev` to `first`. + - Move `first` to `first.next` (which is the next pair of nodes). +6. Return the `next` pointer of the dummy node, which points to the head of the modified list. + +Here's the implementation: ```java -import com_github_leetcode.ListNode; - -/* - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode() {} - * ListNode(int val) { this.val = val; } - * ListNode(int val, ListNode next) { this.val = val; this.next = next; } - * } - */ public class Solution { public ListNode swapPairs(ListNode head) { - if (head == null) { - return null; + // Create a dummy node and point its next to the head + ListNode dummy = new ListNode(0); + dummy.next = head; + + // Initialize pointers + ListNode prev = dummy; + ListNode first, second; + + // Swap pairs of nodes + while (prev.next != null && prev.next.next != null) { + first = prev.next; + second = first.next; + + // Swap nodes + prev.next = second; + first.next = second.next; + second.next = first; + + // Move prev to the next pair of nodes + prev = first; } - int len = getLength(head); - return reverse(head, len); - } - - private int getLength(ListNode curr) { - int cnt = 0; - while (curr != null) { - cnt++; - curr = curr.next; - } - return cnt; - } - - // Recursive function to reverse in groups - private ListNode reverse(ListNode head, int len) { - // base case - if (len < 2) { - return head; - } - ListNode curr = head; - ListNode prev = null; - ListNode next; - for (int i = 0; i < 2; i++) { - // reverse linked list code - next = curr.next; - curr.next = prev; - prev = curr; - curr = next; - } - head.next = reverse(curr, len - 2); - return prev; + + return dummy.next; } } ``` -**Time Complexity (Big O Time):** - -1. The `getLength` function iterates through the linked list once to determine its length, which takes O(n) time, where n is the number of nodes in the list. - -2. The `reverse` function is a recursive function that processes the linked list in pairs of 2 nodes. In each recursive call, it reverses two nodes, which takes constant time O(1). The number of recursive calls is proportional to the length of the list divided by 2 (len / 2). - -Combining these factors, the overall time complexity of the program is O(n), where n is the number of nodes in the input linked list. This is because the dominant factor is the iteration through the list to compute its length. - -**Space Complexity (Big O Space):** - -1. The space complexity of the program is O(1) because it uses a constant amount of additional space for variables like `curr`, `prev`, and `next`. Regardless of the size of the input linked list, the space used for these variables remains constant. - -2. The program does use a call stack for the recursive calls to the `reverse` function, but the maximum depth of the recursion is bounded by the length of the list divided by 2. Therefore, the space used for the call stack is O(n/2), which simplifies to O(n) in big O notation. However, this is still considered O(1) in terms of space complexity because it's not dependent on the input size. - -In summary, the time complexity of the provided program is O(n), and the space complexity is O(1), where n is the number of nodes in the input linked list. +This implementation provides a solution to the "Swap Nodes in Pairs" problem in Java without modifying the values in the list's nodes. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0025_reverse_nodes_in_k_group/readme.md b/src/main/java/g0001_0100/s0025_reverse_nodes_in_k_group/readme.md index 9286f45b..29d5679d 100644 --- a/src/main/java/g0001_0100/s0025_reverse_nodes_in_k_group/readme.md +++ b/src/main/java/g0001_0100/s0025_reverse_nodes_in_k_group/readme.md @@ -48,71 +48,68 @@ You may not alter the values in the list's nodes, only nodes themselves may be c **Follow-up:** Can you solve the problem in O(1) extra memory space? -## Solution +To solve the "Reverse Nodes in k-Group" problem in Java with a `Solution` class, we can reverse the nodes in groups of k using a recursive approach. Here are the steps: + +1. Define a `Solution` class. +2. Define a method named `reverseKGroup` that takes the head of a linked list and an integer k as input and returns the head of the modified list. +3. Define a helper method named `reverse` that takes the head and tail of a sublist as input and reverses the sublist in place. This method returns the new head of the sublist. +4. Create a dummy ListNode object and set its `next` pointer to the head of the input list. This dummy node will serve as the new head of the modified list. +5. Initialize pointers `prev`, `curr`, `next`, and `tail`. Set `prev` and `tail` to the dummy node, and `curr` to the head of the input list. +6. Iterate through the list: + - Move `curr` k steps forward. If it's not possible (i.e., there are less than k nodes left), break the loop. + - Set `next` to the `next` pointer of `curr`. + - Reverse the sublist from `curr` to `next` using the `reverse` method. Update `prev` and `tail` accordingly. + - Move `prev` and `tail` k steps forward to the last node of the reversed sublist. + - Move `curr` to `next`. +7. Return the `next` pointer of the dummy node, which points to the head of the modified list. + +Here's the implementation: ```java -import com_github_leetcode.ListNode; - -/* - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode() {} - * ListNode(int val) { this.val = val; } - * ListNode(int val, ListNode next) { this.val = val; this.next = next; } - * } - */ public class Solution { public ListNode reverseKGroup(ListNode head, int k) { - if (head == null || head.next == null || k == 1) { - return head; - } - int j = 0; - ListNode len = head; - // loop for checking the length of the linklist, if the linklist is less than k, then return - // as it is. - while (j < k) { - if (len == null) { - return head; + // Create a dummy node and point its next to the head + ListNode dummy = new ListNode(0); + dummy.next = head; + + // Initialize pointers + ListNode prev = dummy, curr = head, next, tail; + + // Iterate through the list and reverse in groups of k + while (true) { + // Move curr k steps forward + tail = prev; + for (int i = 0; i < k; i++) { + tail = tail.next; + if (tail == null) return dummy.next; // Less than k nodes left } - len = len.next; - j++; + + next = tail.next; // Save the next pointer of the sublist + tail.next = null; // Disconnect the sublist from the rest of the list + + // Reverse the sublist and update prev and tail pointers + prev.next = reverse(curr, tail); + tail.next = next; // Connect the reversed sublist back to the rest of the list + + // Move prev, tail, and curr to the next group + prev = curr; + curr = next; } - // Reverse linked list logic applied here. - ListNode c = head; - ListNode n = null; - ListNode prev = null; - int i = 0; - // Traverse the while loop for K times to reverse the node in K groups. - while (i != k) { - n = c.next; - c.next = prev; - prev = c; - c = n; - i++; + } + + // Helper method to reverse a sublist from head to tail + private ListNode reverse(ListNode head, ListNode tail) { + ListNode prev = null, curr = head, next; + while (curr != null) { + next = curr.next; + curr.next = prev; + prev = curr; + curr = next; + if (prev == tail) break; } - // C1 is pointing to 1st node of K group, which is now going to point to the next K group - // linklist. - // recursion, for futher remaining linked list. - head.next = reverseKGroup(n, k); - return prev; + return prev; // Return the new head of the reversed sublist } } ``` -**Time Complexity (Big O Time):** - -1. The program first checks if the length of the linked list is less than k by iterating through the list. This operation takes O(k) time. - -2. The main logic of reversing the linked list is contained in a loop that iterates k times (for each group of k nodes). Inside this loop, the reversal of the k nodes takes constant time, O(k). This is because regardless of the size of the input linked list, you are reversing a fixed number of nodes (k) in each iteration. - -3. The program uses recursion to reverse the remaining part of the linked list, which will also be done in groups of k nodes. The depth of the recursion will depend on the length of the input linked list, but each level of recursion deals with a sublist of the original list, which is a fraction of the size. Therefore, the overall time complexity of the recursion can be expressed as O(n), where n is the number of nodes in the input linked list. - -Combining these factors, the overall time complexity of the program is O(n), where n is the number of nodes in the input linked list. The O(k) part is overshadowed by the O(n) complexity. - -**Space Complexity (Big O Space):** - -1. The space complexity of the program is O(k), where k is the group size. This is because in each iteration of the reversal loop, a constant amount of additional space is used for variables like `c`, `n`, `prev`, and `i`. The recursion also consumes space on the call stack, but the maximum depth of the recursion is bounded by the length of the list divided by k, so the space used for the call stack can be considered O(n/k), which simplifies to O(n) when analyzing in big O notation. - -In summary, the time complexity of the provided program is O(n), and the space complexity is O(k) for the reversal logic within each group of k nodes, and O(n) for the space used on the call stack during recursion, where n is the number of nodes in the input linked list and k is the group size. +This implementation provides a solution to the "Reverse Nodes in k-Group" problem in Java without modifying the values in the list's nodes. It recursively reverses the nodes in groups of k. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0031_next_permutation/readme.md b/src/main/java/g0001_0100/s0031_next_permutation/readme.md index 423f3be5..895a57a2 100644 --- a/src/main/java/g0001_0100/s0031_next_permutation/readme.md +++ b/src/main/java/g0001_0100/s0031_next_permutation/readme.md @@ -40,56 +40,63 @@ The replacement must be **[in place](http://en.wikipedia.org/wiki/In-place_algor * `1 <= nums.length <= 100` * `0 <= nums[i] <= 100` -## Solution +To solve the "Next Permutation" problem in Java with a `Solution` class, we can follow these steps: + +1. Define a `Solution` class. +2. Define a method named `nextPermutation` that takes an integer array `nums` as input and modifies it to find the next permutation in lexicographic order. +3. Find the first index `i` from the right such that `nums[i] > nums[i - 1]`. If no such index exists, reverse the entire array, as it's already the last permutation. +4. Find the smallest index `j` from the right such that `nums[j] > nums[i - 1]`. +5. Swap `nums[i - 1]` with `nums[j]`. +6. Reverse the suffix of the array starting from index `i`. + +Here's the implementation: ```java public class Solution { public void nextPermutation(int[] nums) { - if (nums == null || nums.length <= 1) { + int n = nums.length; + + // Step 1: Find the first index i from the right such that nums[i] > nums[i - 1] + int i = n - 1; + while (i > 0 && nums[i] <= nums[i - 1]) { + i--; + } + + // Step 2: If no such index exists, reverse the entire array + if (i == 0) { + reverse(nums, 0, n - 1); return; } - int i = nums.length - 2; - while (i >= 0 && nums[i] >= nums[i + 1]) { - i--; + + // Step 3: Find the smallest index j from the right such that nums[j] > nums[i - 1] + int j = n - 1; + while (nums[j] <= nums[i - 1]) { + j--; } - if (i >= 0) { - int j = nums.length - 1; - while (nums[j] <= nums[i]) { - j--; - } - swap(nums, i, j); + + // Step 4: Swap nums[i - 1] with nums[j] + swap(nums, i - 1, j); + + // Step 5: Reverse the suffix of the array starting from index i + reverse(nums, i, n - 1); + } + + // Helper method to reverse a portion of the array + private void reverse(int[] nums, int start, int end) { + while (start < end) { + swap(nums, start, end); + start++; + end--; } - reverse(nums, i + 1, nums.length - 1); } - + + // Helper method to swap two elements in the array private void swap(int[] nums, int i, int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } - - private void reverse(int[] nums, int i, int j) { - while (i < j) { - swap(nums, i++, j--); - } - } } ``` -**Time Complexity (Big O Time):** - -1. The program first iterates backward through the array to find the first element `i` where `nums[i] < nums[i+1]`. This operation takes O(n) time, where n is the length of the array. - -2. If such an element `i` is found, the program then iterates backward again to find the smallest element `j` to the right of `i` such that `nums[j] > nums[i]`. This operation also takes O(n) time, where n is the length of the array. - -3. After finding `i` and `j`, the program swaps these two elements, which takes constant time O(1). - -4. Finally, the program reverses the subarray to the right of `i` (from index `i+1` to the end of the array), which takes O(n) time in the worst case. - -Overall, the time complexity of the program is dominated by the two linear scans through the array, so it's O(n), where n is the length of the input array `nums`. - -**Space Complexity (Big O Space):** - -The space complexity of the program is O(1) because it uses a constant amount of additional space for variables like `i`, `j`, and `temp`. Regardless of the size of the input array, the space used by these variables remains constant. - -In summary, the time complexity of the provided program is O(n), and the space complexity is O(1), where n is the length of the input array `nums`. +This implementation provides a solution to the "Next Permutation" problem in Java. It finds the next lexicographically greater permutation of the given array `nums` and modifies it in place. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0032_longest_valid_parentheses/readme.md b/src/main/java/g0001_0100/s0032_longest_valid_parentheses/readme.md index 34451c06..aec15dcc 100644 --- a/src/main/java/g0001_0100/s0032_longest_valid_parentheses/readme.md +++ b/src/main/java/g0001_0100/s0032_longest_valid_parentheses/readme.md @@ -34,63 +34,49 @@ Given a string containing just the characters `'('` and `')'`, find the length o * 0 <= s.length <= 3 * 104 * `s[i]` is `'('`, or `')'`. -## Solution +To solve the "Longest Valid Parentheses" problem in Java with a `Solution` class, we can follow these steps: + +1. Define a `Solution` class. +2. Define a method named `longestValidParentheses` that takes a string `s` as input and returns an integer representing the length of the longest valid parentheses substring. +3. Initialize a stack to store the indices of characters. +4. Initialize a variable `maxLen` to store the maximum length of valid parentheses found so far. +5. Push `-1` onto the stack to mark the starting point of a potential valid substring. +6. Iterate through each character of the string: + - If the character is `'('`, push its index onto the stack. + - If the character is `')'`: + - Pop the top index from the stack. + - If the stack is empty after popping, push the current index onto the stack to mark the starting point of the next potential valid substring. + - Otherwise, update `maxLen` with the maximum of the current `maxLen` and `i - stack.peek()`, where `i` is the current index and `stack.peek()` is the index at the top of the stack. +7. Return `maxLen`. + +Here's the implementation: ```java +import java.util.Stack; + public class Solution { public int longestValidParentheses(String s) { - int max = 0; - int left = 0; - int right = 0; - int n = s.length(); - char ch; - for (int i = 0; i < n; i++) { - ch = s.charAt(i); - if (ch == '(') { - left++; - } else { - right++; - } - if (right > left) { - left = 0; - right = 0; - } - if (left == right) { - max = Math.max(max, left + right); - } - } - left = 0; - right = 0; - for (int i = n - 1; i >= 0; i--) { - ch = s.charAt(i); - if (ch == '(') { - left++; - } else { - right++; - } - if (left > right) { - left = 0; - right = 0; - } - if (left == right) { - max = Math.max(max, left + right); + int maxLen = 0; + Stack stack = new Stack<>(); + stack.push(-1); // Mark the starting point of a potential valid substring + + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '(') { + stack.push(i); + } else { // c == ')' + stack.pop(); + if (stack.isEmpty()) { + stack.push(i); // Mark the starting point of the next potential valid substring + } else { + maxLen = Math.max(maxLen, i - stack.peek()); + } } } - return max; + + return maxLen; } } ``` -**Time Complexity (Big O Time):** - -1. The program iterates through the input string `s` twice. In the first loop, it goes from left to right, and in the second loop, it goes from right to left. Each loop has a linear time complexity of O(n), where n is the length of the input string. - -2. Within each loop, there are constant time operations like character comparisons and arithmetic calculations. These operations do not depend on the size of the input string and can be considered O(1). - -Combining these factors, the overall time complexity of the program is O(n), where n is the length of the input string `s`. The two passes through the string do not make it O(2n) because constant factors are ignored in big O notation. - -**Space Complexity (Big O Space):** - -The space complexity of the program is O(1), which means it uses a constant amount of additional space regardless of the size of the input string `s`. The variables `max`, `left`, `right`, `n`, and `ch` all occupy constant space, and the program does not use any additional data structures or memory that scales with the input size. - -In summary, the time complexity of the provided program is O(n), and the space complexity is O(1), where n is the length of the input string `s`. +This implementation provides a solution to the "Longest Valid Parentheses" problem in Java. It finds the length of the longest valid parentheses substring in the given string `s`. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0033_search_in_rotated_sorted_array/readme.md b/src/main/java/g0001_0100/s0033_search_in_rotated_sorted_array/readme.md index f49547ee..66c14dfa 100644 --- a/src/main/java/g0001_0100/s0033_search_in_rotated_sorted_array/readme.md +++ b/src/main/java/g0001_0100/s0033_search_in_rotated_sorted_array/readme.md @@ -39,55 +39,56 @@ You must write an algorithm with `O(log n)` runtime complexity. * `nums` is an ascending array that is possibly rotated. * -104 <= target <= 104 -## Solution +To solve the "Search in Rotated Sorted Array" problem in Java with a `Solution` class, we can follow these steps: + +1. Define a `Solution` class. +2. Define a method named `search` that takes an integer array `nums` and an integer `target` as input and returns an integer representing the index of `target` in `nums`. If `target` is not found, return `-1`. +3. Implement the binary search algorithm to find the index of `target` in the rotated sorted array. +4. Set the left pointer `left` to 0 and the right pointer `right` to the length of `nums` minus 1. +5. While `left` is less than or equal to `right`: + - Calculate the middle index `mid` as `(left + right) / 2`. + - If `nums[mid]` is equal to `target`, return `mid`. + - Check if the left half of the array (`nums[left]` to `nums[mid]`) is sorted: + - If `nums[left] <= nums[mid]` and `nums[left] <= target < nums[mid]`, update `right = mid - 1`. + - Otherwise, update `left = mid + 1`. + - Otherwise, check if the right half of the array (`nums[mid]` to `nums[right]`) is sorted: + - If `nums[mid] <= nums[right]` and `nums[mid] < target <= nums[right]`, update `left = mid + 1`. + - Otherwise, update `right = mid - 1`. +6. If `target` is not found, return `-1`. + +Here's the implementation: ```java public class Solution { public int search(int[] nums, int target) { - int mid; - int lo = 0; - int hi = nums.length - 1; - while (lo <= hi) { - mid = ((hi - lo) >> 1) + lo; - if (target == nums[mid]) { + int left = 0; + int right = nums.length - 1; + + while (left <= right) { + int mid = left + (right - left) / 2; + + if (nums[mid] == target) { return mid; } - // if this is true, then the possible rotation can only be in the second half - if (nums[lo] <= nums[mid]) { - // the target is in the first half only if it's - if (nums[lo] <= target && target <= nums[mid]) { - // included - hi = mid - 1; + + if (nums[left] <= nums[mid]) { + if (nums[left] <= target && target < nums[mid]) { + right = mid - 1; } else { - // between nums[lo] and nums[mid] - lo = mid + 1; + left = mid + 1; } - // otherwise, the possible rotation can only be in the first half - } else if (nums[mid] <= target && target <= nums[hi]) { - // the target is in the second half only if it's included - lo = mid + 1; } else { - // between nums[hi] and nums[mid] - hi = mid - 1; + if (nums[mid] < target && target <= nums[right]) { + left = mid + 1; + } else { + right = mid - 1; + } } } + return -1; } } ``` -**Time Complexity (Big O Time):** - -The time complexity of this program is O(log n), where n is the number of elements in the input `nums` array. Here's why: - -1. The program performs a binary search to find the target element. In each step of the binary search, it reduces the search range by half. - -2. The while loop runs until the `lo` pointer is less than or equal to the `hi` pointer, and in each iteration, it reduces the search range by half. - -3. Therefore, the number of iterations in the binary search is proportional to log2(n), where n is the number of elements in the input array. This gives us the time complexity of O(log n). - -**Space Complexity (Big O Space):** - -The space complexity of this program is O(1), which means it uses a constant amount of additional space regardless of the size of the input array `nums`. The program only uses a few integer variables (`mid`, `lo`, `hi`) and does not use any additional data structures or memory that scales with the input size. - -In summary, the time complexity of the provided program is O(log n), and the space complexity is O(1), where n is the number of elements in the input array `nums`. +This implementation provides a solution to the "Search in Rotated Sorted Array" problem in Java. It searches for the index of `target` in the rotated sorted array `nums`. The algorithm has a time complexity of O(log n). \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0034_find_first_and_last_position_of_element_in_sorted_array/readme.md b/src/main/java/g0001_0100/s0034_find_first_and_last_position_of_element_in_sorted_array/readme.md index 71038452..b1dd52b1 100644 --- a/src/main/java/g0001_0100/s0034_find_first_and_last_position_of_element_in_sorted_array/readme.md +++ b/src/main/java/g0001_0100/s0034_find_first_and_last_position_of_element_in_sorted_array/readme.md @@ -36,47 +36,70 @@ You must write an algorithm with `O(log n)` runtime complexity. * `nums` is a non-decreasing array. * -109 <= target <= 109 -## Solution +To solve the "Find First and Last Position of Element in Sorted Array" problem in Java with a `Solution` class, we can follow these steps: + +1. Define a `Solution` class. +2. Define a method named `searchRange` that takes an integer array `nums` and an integer `target` as input and returns an integer array representing the starting and ending positions of `target` in `nums`. If `target` is not found, return `[-1, -1]`. +3. Implement binary search to find the first and last occurrences of `target`. +4. Set the left pointer `left` to 0 and the right pointer `right` to the length of `nums` minus 1. +5. Initialize two variables `firstOccurrence` and `lastOccurrence` to -1. +6. Perform two binary search operations: + - First, find the first occurrence of `target`: + - While `left` is less than or equal to `right`: + - Calculate the middle index `mid` as `(left + right) / 2`. + - If `nums[mid]` is equal to `target`, update `firstOccurrence = mid` and continue searching on the left half by updating `right = mid - 1`. + - Otherwise, if `target` is less than `nums[mid]`, update `right = mid - 1`. + - Otherwise, update `left = mid + 1`. + - Second, find the last occurrence of `target`: + - Reset `left` to 0 and `right` to the length of `nums` minus 1. + - While `left` is less than or equal to `right`: + - Calculate the middle index `mid` as `(left + right) / 2`. + - If `nums[mid]` is equal to `target`, update `lastOccurrence = mid` and continue searching on the right half by updating `left = mid + 1`. + - Otherwise, if `target` is greater than `nums[mid]`, update `left = mid + 1`. + - Otherwise, update `right = mid - 1`. +7. Return the array `[firstOccurrence, lastOccurrence]`. + +Here's the implementation: ```java public class Solution { public int[] searchRange(int[] nums, int target) { - int[] ans = new int[2]; - ans[0] = helper(nums, target, false); - ans[1] = helper(nums, target, true); - return ans; - } - - private int helper(int[] nums, int target, boolean equals) { - int l = 0; - int r = nums.length - 1; - int result = -1; - while (l <= r) { - int mid = l + (r - l) / 2; + int left = 0; + int right = nums.length - 1; + int firstOccurrence = -1; + int lastOccurrence = -1; + + // Find first occurrence + while (left <= right) { + int mid = left + (right - left) / 2; if (nums[mid] == target) { - result = mid; + firstOccurrence = mid; + right = mid - 1; + } else if (target < nums[mid]) { + right = mid - 1; + } else { + left = mid + 1; } - if (nums[mid] < target || (nums[mid] == target && equals)) { - l = mid + 1; + } + + // Find last occurrence + left = 0; + right = nums.length - 1; + while (left <= right) { + int mid = left + (right - left) / 2; + if (nums[mid] == target) { + lastOccurrence = mid; + left = mid + 1; + } else if (target < nums[mid]) { + right = mid - 1; } else { - r = mid - 1; + left = mid + 1; } } - return result; + + return new int[]{firstOccurrence, lastOccurrence}; } } ``` -**Time Complexity (Big O Time):** - -1. The program performs two binary searches, one to find the leftmost occurrence of the target value and another to find the rightmost occurrence. - -2. Each binary search operates on a sorted array of length n, and in each step, it reduces the search range by half. - -3. Therefore, the time complexity of each binary search is O(log n), and since the program performs two binary searches sequentially, the overall time complexity is still O(log n). - -**Space Complexity (Big O Space):** - -The space complexity of the program is O(1), which means it uses a constant amount of additional space regardless of the size of the input array `nums`. The program only uses a few integer variables (`l`, `r`, `result`, `mid`) and an integer array of constant size to store the result. - -In summary, the time complexity of the provided program is O(log n), and the space complexity is O(1), where n is the number of elements in the input array `nums`. +This implementation provides a solution to the "Find First and Last Position of Element in Sorted Array" problem in Java. It returns the starting and ending positions of `target` in `nums` using binary search, with a time complexity of O(log n). \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0035_search_insert_position/readme.md b/src/main/java/g0001_0100/s0035_search_insert_position/readme.md index 80ab4ffa..dca3808a 100644 --- a/src/main/java/g0001_0100/s0035_search_insert_position/readme.md +++ b/src/main/java/g0001_0100/s0035_search_insert_position/readme.md @@ -46,38 +46,41 @@ You must write an algorithm with `O(log n)` runtime complexity. * `nums` contains **distinct** values sorted in **ascending** order. * -104 <= target <= 104 -## Solution +To solve the "Search Insert Position" problem in Java with a `Solution` class, we can follow these steps: + +1. Define a `Solution` class. +2. Define a method named `searchInsert` that takes an integer array `nums` and an integer `target` as input and returns an integer representing the index where `target` would be inserted in order. +3. Implement binary search to find the insertion position of `target`. +4. Set the left pointer `left` to 0 and the right pointer `right` to the length of `nums` minus 1. +5. While `left` is less than or equal to `right`: + - Calculate the middle index `mid` as `(left + right) / 2`. + - If `nums[mid]` is equal to `target`, return `mid`. + - If `target` is less than `nums[mid]`, update `right = mid - 1`. + - If `target` is greater than `nums[mid]`, update `left = mid + 1`. +6. If `target` is not found in `nums`, return the value of `left`, which represents the index where `target` would be inserted in order. + +Here's the implementation: ```java public class Solution { public int searchInsert(int[] nums, int target) { - int lo = 0; - int hi = nums.length - 1; - while (lo <= hi) { - int mid = lo + (hi - lo) / 2; - if (target == nums[mid]) { + int left = 0; + int right = nums.length - 1; + + while (left <= right) { + int mid = left + (right - left) / 2; + if (nums[mid] == target) { return mid; } else if (target < nums[mid]) { - hi = mid - 1; - } else if (target > nums[mid]) { - lo = mid + 1; + right = mid - 1; + } else { + left = mid + 1; } } - return lo; + + return left; } } ``` -**Time Complexity (Big O Time):** - -1. The program performs a binary search on a sorted array of length n. In each step of the binary search, it reduces the search range by half. - -2. The while loop runs until the `lo` pointer is less than or equal to the `hi` pointer, and in each iteration, it reduces the search range by half. - -3. Therefore, the number of iterations in the binary search is proportional to log2(n), where n is the number of elements in the input array. This gives us the time complexity of O(log n). - -**Space Complexity (Big O Space):** - -The space complexity of the program is O(1), which means it uses a constant amount of additional space regardless of the size of the input array `nums`. The program only uses a few integer variables (`lo`, `hi`, `mid`) and does not use any additional data structures or memory that scales with the input size. - -In summary, the time complexity of the provided program is O(log n), and the space complexity is O(1), where n is the number of elements in the input array `nums`. +This implementation provides a solution to the "Search Insert Position" problem in Java. It returns the index where `target` would be inserted in `nums` using binary search, with a time complexity of O(log n). \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0039_combination_sum/readme.md b/src/main/java/g0001_0100/s0039_combination_sum/readme.md index fa5b9179..7e30d5e7 100644 --- a/src/main/java/g0001_0100/s0039_combination_sum/readme.md +++ b/src/main/java/g0001_0100/s0039_combination_sum/readme.md @@ -54,61 +54,53 @@ It is **guaranteed** that the number of unique combinations that sum up to `targ * All elements of `candidates` are **distinct**. * `1 <= target <= 500` -## Solution +To solve the "Combination Sum" problem in Java with a `Solution` class, we can follow these steps: + +1. Define a `Solution` class. +2. Define a method named `combinationSum` that takes an array of integers `candidates` and an integer `target` as input and returns a list of lists containing all unique combinations of `candidates` where the chosen numbers sum to `target`. +3. Implement backtracking to explore all possible combinations of candidates. +4. Sort the `candidates` array to ensure that duplicates are grouped together. +5. Create a recursive helper method named `backtrack` that takes parameters: + - A list to store the current combination. + - An integer representing the starting index in the `candidates` array. + - The current sum of the combination. +6. In the `backtrack` method: + - If the current sum equals the target, add the current combination to the result list. + - Iterate over the candidates starting from the current index. + - Add the current candidate to the combination. + - Recursively call the `backtrack` method with the updated combination, index, and sum. + - Remove the last added candidate from the combination to backtrack. +7. Call the `backtrack` method with an empty combination list, starting index 0, and sum 0. +8. Return the result list containing all unique combinations. + +Here's the implementation: ```java import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class Solution { - public List> combinationSum(int[] coins, int amount) { - List> ans = new ArrayList<>(); - List subList = new ArrayList<>(); - combinationSumRec(coins.length, coins, amount, subList, ans); - return ans; + public List> combinationSum(int[] candidates, int target) { + List> result = new ArrayList<>(); + Arrays.sort(candidates); // Sort the candidates to ensure duplicates are grouped together + backtrack(result, new ArrayList<>(), candidates, target, 0); + return result; } - private void combinationSumRec( - int n, int[] coins, int amount, List subList, List> ans) { - if (amount == 0 || n == 0) { - if (amount == 0) { - List base = new ArrayList<>(subList); - ans.add(base); - } + private void backtrack(List> result, List combination, int[] candidates, int target, int start) { + if (target == 0) { + result.add(new ArrayList<>(combination)); return; } - if (amount - coins[n - 1] >= 0) { - subList.add(coins[n - 1]); - combinationSumRec(n, coins, amount - coins[n - 1], subList, ans); - subList.remove(subList.size() - 1); + + for (int i = start; i < candidates.length && candidates[i] <= target; i++) { + combination.add(candidates[i]); + backtrack(result, combination, candidates, target - candidates[i], i); // Use the same candidate again + combination.remove(combination.size() - 1); // Backtrack by removing the last candidate } - combinationSumRec(n - 1, coins, amount, subList, ans); } } ``` -**Time Complexity (Big O Time):** - -1. The program uses a recursive function, `combinationSumRec`, to generate combinations. In the worst case, it explores all possible combinations. - -2. For each coin, it has two choices: either include the coin in the combination or exclude it. This results in a binary tree-like structure for the recursive calls, where each level of the tree represents a different coin and has two branches for including or excluding the coin. - -3. In the worst case, the binary tree has a height of n (the number of coins). This means that the program makes 2^n recursive calls. - -4. In each recursive call, the program performs constant-time operations to add or remove elements from the `subList`, which can be considered O(1). - -5. Therefore, the overall time complexity is O(2^n), where n is the number of coins. - -**Space Complexity (Big O Space):** - -1. The space complexity of the program is determined by the space used for the call stack during the recursion and the space used for the `subList` and `ans` list. - -2. The maximum depth of the recursion is n (the number of coins), which means the space used for the call stack is O(n). - -3. The `subList` stores the current combination, and its size is bounded by the number of coins. In the worst case, it can have n elements. - -4. The `ans` list stores all valid combinations, and its size is determined by the number of valid combinations. In the worst case, it can also have a size of 2^n, considering all possible combinations. - -5. Therefore, the space complexity of the program is O(n + 2^n), where n is the number of coins. - -In summary, the time complexity of the provided program is O(2^n), and the space complexity is O(n + 2^n), where n is the number of coins. +This implementation provides a solution to the "Combination Sum" problem in Java. It explores all possible combinations of candidates using backtracking and returns the unique combinations whose sum equals the target. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0041_first_missing_positive/readme.md b/src/main/java/g0001_0100/s0041_first_missing_positive/readme.md index e492e0a1..942a59ae 100644 --- a/src/main/java/g0001_0100/s0041_first_missing_positive/readme.md +++ b/src/main/java/g0001_0100/s0041_first_missing_positive/readme.md @@ -32,58 +32,45 @@ You must implement an algorithm that runs in `O(n)` time and uses constant extra * 1 <= nums.length <= 5 * 105 * -231 <= nums[i] <= 231 - 1 -## Solution +To solve the "First Missing Positive" problem in Java with a `Solution` class, we can follow these steps: + +1. Define a `Solution` class. +2. Define a method named `firstMissingPositive` that takes an array of integers `nums` as input and returns the smallest missing positive integer. +3. Iterate through the array and mark the positive integers found by negating the value at the corresponding index. +4. Iterate through the modified array again and return the index of the first positive number (which is the smallest missing positive integer). +5. If no positive number is found, return `nums.length + 1`. + +Here's the implementation: ```java public class Solution { public int firstMissingPositive(int[] nums) { - for (int i = 0; i < nums.length; i++) { - if (nums[i] <= 0 || nums[i] > nums.length || nums[i] == i + 1) { - continue; + int n = nums.length; + + // Mark positive integers found by negating the value at the corresponding index + for (int i = 0; i < n; i++) { + if (nums[i] > 0 && nums[i] <= n) { + int pos = nums[i] - 1; + if (nums[pos] != nums[i]) { + int temp = nums[pos]; + nums[pos] = nums[i]; + nums[i] = temp; + i--; // Revisit the swapped number + } } - dfs(nums, nums[i]); } - for (int i = 0; i < nums.length; i++) { + + // Find the first positive number (smallest missing positive integer) + for (int i = 0; i < n; i++) { if (nums[i] != i + 1) { return i + 1; } } - return nums.length + 1; - } - private void dfs(int[] nums, int val) { - if (val <= 0 || val > nums.length || val == nums[val - 1]) { - return; - } - int temp = nums[val - 1]; - nums[val - 1] = val; - dfs(nums, temp); + // If no positive number is found, return nums.length + 1 + return n + 1; } } ``` -**Time Complexity (Big O Time):** - -1. The program contains two loops: - - The first loop iterates through the array `nums` once to perform a depth-first search (DFS) on the elements. - - The second loop iterates through the modified `nums` array once to find the first missing positive integer. - -2. In the worst case, the first loop may visit every element in the `nums` array, which has a length of n (the number of elements in the array). - -3. The DFS recursion also runs in the worst case for every element in the array. In the worst case, the recursion depth could be n (for example, if the array contains all positive integers from 1 to n). - -4. The second loop always iterates through the entire array once. - -5. Therefore, the overall time complexity of the program is O(n), where n is the length of the input array `nums`. - -**Space Complexity (Big O Space):** - -1. The space complexity of the program is determined by the space used for the call stack during the DFS recursion and the constant space used for variables. - -2. The maximum depth of the DFS recursion is bounded by n in the worst case (when the array contains all positive integers from 1 to n). Therefore, the space used for the call stack is O(n). - -3. The program uses a few integer variables (`i`, `val`, `temp`) and does not use any additional data structures that scale with the input size. - -4. Therefore, the overall space complexity of the program is O(n) due to the space used for the call stack, where n is the length of the input array `nums`. - -In summary, the time complexity of the provided program is O(n), and the space complexity is O(n), where n is the number of elements in the input array `nums`. +This implementation provides a solution to the "First Missing Positive" problem in Java. It marks positive integers found by negating the value at the corresponding index and then iterates through the modified array to find the smallest missing positive integer. If no positive number is found, it returns `nums.length + 1`. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0042_trapping_rain_water/readme.md b/src/main/java/g0001_0100/s0042_trapping_rain_water/readme.md index f95d6bad..52514180 100644 --- a/src/main/java/g0001_0100/s0042_trapping_rain_water/readme.md +++ b/src/main/java/g0001_0100/s0042_trapping_rain_water/readme.md @@ -29,57 +29,44 @@ Given `n` non-negative integers representing an elevation map where the width of * 1 <= n <= 2 * 104 * 0 <= height[i] <= 105 -## Solution +To solve the "Trapping Rain Water" problem in Java with a `Solution` class, we can follow these steps: + +1. Define a `Solution` class. +2. Define a method named `trap` that takes an array of integers `height` as input and returns the amount of water it can trap after raining. +3. Initialize two pointers `left` and `right` at the beginning and end of the array respectively. +4. Initialize two variables `leftMax` and `rightMax` to keep track of the maximum height of bars encountered from the left and right directions respectively. +5. Iterate through the array using the two pointers: + - Update `leftMax` as the maximum of `leftMax` and `height[left]`. + - Update `rightMax` as the maximum of `rightMax` and `height[right]`. + - If `height[left] < height[right]`, calculate the water trapped at the current position using `leftMax` and subtract the height of the current bar. Move `left` pointer to the right. + - Otherwise, calculate the water trapped at the current position using `rightMax` and subtract the height of the current bar. Move `right` pointer to the left. +6. Continue this process until the two pointers meet. +7. Return the total amount of water trapped. + +Here's the implementation: ```java public class Solution { public int trap(int[] height) { - int l = 0; - int r = height.length - 1; - int res = 0; - int lowerWall = 0; - while (l < r) { - int lVal = height[l]; - int rVal = height[r]; - // If left is smaller than right ptr, make the lower wall the bigger of lVal and its - // current size - if (lVal < rVal) { - // If lVal has gone up, move the lowerWall upp - lowerWall = Math.max(lVal, lowerWall); - // Add the water level at current point - // Calculate this by taking the current value and subtracting it from the lower wall - // size - // We know that this is the lower wall because we've already determined that lVal < - // rVal - res += lowerWall - lVal; - // Move left ptr along - l++; + int left = 0, right = height.length - 1; + int leftMax = 0, rightMax = 0; + int trappedWater = 0; + + while (left < right) { + if (height[left] < height[right]) { + leftMax = Math.max(leftMax, height[left]); + trappedWater += leftMax - height[left]; + left++; } else { - // Do the same thing, except now we know that the lowerWall is the right side. - lowerWall = Math.max(rVal, lowerWall); - res += lowerWall - rVal; - r--; + rightMax = Math.max(rightMax, height[right]); + trappedWater += rightMax - height[right]; + right--; } } - return res; + + return trappedWater; } } ``` -**Time Complexity (Big O Time):** - -1. The program uses two pointers, `l` (left) and `r` (right), that initially start at the leftmost and rightmost elements of the input `height` array. The pointers move towards each other until they meet. - -2. In each step of the loop, the program computes the trapped rainwater at the current position based on the lower wall (the smaller of the heights at `height[l]` and `height[r]`). - -3. The loop runs until the `l` pointer is less than the `r` pointer, and in each iteration, it either increments `l` or decrements `r`. Since the pointers move towards each other and never move backward, the loop executes at most `n` times, where `n` is the number of elements in the input `height` array. - -4. The operations within the loop, including comparisons, arithmetic, and mathematical operations (e.g., `Math.max`), are all constant time operations, so they do not significantly impact the overall time complexity. - -5. Therefore, the time complexity of the program is O(n), where `n` is the number of elements in the input array `height`. - -**Space Complexity (Big O Space):** - -The space complexity of the program is O(1), which means it uses a constant amount of additional space regardless of the size of the input array `height`. The program only uses a few integer variables (`l`, `r`, `res`, `lowerWall`, `lVal`, and `rVal`) and does not use any additional data structures or memory that scales with the input size. - -In summary, the time complexity of the provided program is O(n), and the space complexity is O(1), where `n` is the number of elements in the input array `height`. +This implementation provides a solution to the "Trapping Rain Water" problem in Java. It calculates the amount of water that can be trapped between bars by using two pointers to track the left and right boundaries and two variables to track the maximum heights of bars encountered from the left and right directions. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0045_jump_game_ii/readme.md b/src/main/java/g0001_0100/s0045_jump_game_ii/readme.md index 72b5e32d..5ac104ee 100644 --- a/src/main/java/g0001_0100/s0045_jump_game_ii/readme.md +++ b/src/main/java/g0001_0100/s0045_jump_game_ii/readme.md @@ -32,43 +32,36 @@ You can assume that you can always reach the last index. * 1 <= nums.length <= 104 * `0 <= nums[i] <= 1000` -## Solution +To solve the "Jump Game II" problem in Java with a `Solution` class, we can follow these steps: + +1. Define a `Solution` class. +2. Define a method named `jump` that takes an array of non-negative integers `nums` as input and returns the minimum number of jumps required to reach the last index. +3. Initialize variables `maxReach`, `steps`, and `end` to keep track of the maximum reachable position, the number of steps taken, and the end position respectively. Initialize `maxReach` to 0 and `end` to 0. +4. Iterate through the array from index 0 to `nums.length - 2`: + - Update `maxReach` as the maximum of `maxReach` and `i + nums[i]`. + - If the current index `i` equals `end`, update `end` to `maxReach` and increment `steps`. +5. Return `steps`. + +Here's the implementation: ```java public class Solution { public int jump(int[] nums) { - int length = 0; - int maxLength = 0; - int minJump = 0; - for (int i = 0; i < nums.length - 1; ++i) { - length--; - maxLength--; - maxLength = Math.max(maxLength, nums[i]); - if (length <= 0) { - length = maxLength; - minJump++; - } - if (length >= nums.length - i - 1) { - return minJump; + int maxReach = 0; + int steps = 0; + int end = 0; + + for (int i = 0; i < nums.length - 1; i++) { + maxReach = Math.max(maxReach, i + nums[i]); + if (i == end) { + end = maxReach; + steps++; } } - return minJump; + + return steps; } } ``` -**Time Complexity (Big O Time):** - -1. The program uses a single loop that iterates through the elements of the `nums` array from left to right. - -2. In each iteration, it performs constant time operations such as arithmetic, comparisons, and calls to `Math.max`. These operations do not depend on the size of the input array. - -3. The loop runs until the second-to-last element of the array (i.e., `i < nums.length - 1`), so the number of iterations is at most `n - 1`, where `n` is the number of elements in the input array. - -4. Therefore, the overall time complexity of the program is O(n), where `n` is the number of elements in the input array `nums`. - -**Space Complexity (Big O Space):** - -1. The space complexity of the program is O(1), which means it uses a constant amount of additional space regardless of the size of the input array `nums`. The program only uses a few integer variables (`length`, `maxLength`, `minJump`, and `i`) and does not use any additional data structures or memory that scales with the input size. - -In summary, the time complexity of the provided program is O(n), and the space complexity is O(1), where `n` is the number of elements in the input array `nums`. +This implementation provides a solution to the "Jump Game II" problem in Java. It calculates the minimum number of jumps required to reach the last index by iterating through the array and updating the maximum reachable position and the end position accordingly. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0046_permutations/readme.md b/src/main/java/g0001_0100/s0046_permutations/readme.md index 6fa192f2..0d8b8a06 100644 --- a/src/main/java/g0001_0100/s0046_permutations/readme.md +++ b/src/main/java/g0001_0100/s0046_permutations/readme.md @@ -31,7 +31,20 @@ Given an array `nums` of distinct integers, return _all the possible permutation * `-10 <= nums[i] <= 10` * All the integers of `nums` are **unique**. -## Solution +To solve the "Permutations" problem in Java with a `Solution` class, we can follow these steps: + +1. Define a `Solution` class. +2. Define a method named `permute` that takes an array of distinct integers `nums` as input and returns a list of all possible permutations. +3. Create an empty list to store the result permutations. +4. Call a recursive helper function named `permuteHelper` to generate permutations. +5. Inside the `permuteHelper` function: + - If the current permutation size equals the length of the input array `nums`, add a copy of the current permutation to the result list. + - Otherwise, iterate through each element of `nums`: + - If the current element is not already in the permutation, add it to the current permutation, and recursively call `permuteHelper` with the updated permutation and the remaining elements of `nums`. + - After the recursive call, remove the last element from the permutation to backtrack. +6. Return the result list. + +Here's the implementation: ```java import java.util.ArrayList; @@ -39,55 +52,26 @@ import java.util.List; public class Solution { public List> permute(int[] nums) { - if (nums == null || nums.length == 0) { - return new ArrayList<>(); - } - List> finalResult = new ArrayList<>(); - permuteRecur(nums, finalResult, new ArrayList<>(), new boolean[nums.length]); - return finalResult; + List> result = new ArrayList<>(); + permuteHelper(nums, new ArrayList<>(), result); + return result; } - private void permuteRecur( - int[] nums, List> finalResult, List currResult, boolean[] used) { - if (currResult.size() == nums.length) { - finalResult.add(new ArrayList<>(currResult)); + private void permuteHelper(int[] nums, List current, List> result) { + if (current.size() == nums.length) { + result.add(new ArrayList<>(current)); return; } - for (int i = 0; i < nums.length; i++) { - if (used[i]) { - continue; + + for (int num : nums) { + if (!current.contains(num)) { + current.add(num); + permuteHelper(nums, current, result); + current.remove(current.size() - 1); } - currResult.add(nums[i]); - used[i] = true; - permuteRecur(nums, finalResult, currResult, used); - used[i] = false; - currResult.remove(currResult.size() - 1); } } } ``` -**Time Complexity (Big O Time):** - -1. The program uses a recursive function, `permuteRecur`, to generate permutations. In the worst case, it explores all possible permutations. - -2. The recursive function is called once for each element in the `nums` array, and in each call, it has a loop that iterates through the `nums` array. Therefore, the program generates `n!` permutations, where `n` is the number of elements in the input array. - -3. The time complexity of generating each permutation is O(n), where `n` is the number of elements in the input array, because in each recursive call, we iterate through the `nums` array once. - -4. Therefore, the overall time complexity of the program is O(n * n!), where `n` is the number of elements in the input array `nums`. This is because we generate `n!` permutations, and generating each permutation takes O(n) time. - -**Space Complexity (Big O Space):** - -1. The space complexity of the program is determined by the space used for the call stack during the recursion and the space used for data structures to store permutations. - -2. During the recursive calls, the call stack can have a depth of up to `n`, where `n` is the number of elements in the input array `nums`. This is because the recursive function makes `n` recursive calls, each corresponding to an element in `nums`. - -3. The program uses a few data structures: - - `finalResult`: A list of lists to store permutations. In the worst case, it can contain `n!` permutations. - - `currResult`: A list to store the current permutation being generated. Its size is at most `n`. - - `used`: A boolean array to keep track of whether an element has been used in the current permutation. It has a size of `n`. - -4. Therefore, the overall space complexity of the program is O(n + n!) in the worst case, where `n` is the number of elements in the input array `nums`. The dominant factor is `n!` due to the storage of permutations. - -In summary, the time complexity of the provided program is O(n * n!), and the space complexity is O(n + n!) in the worst case, where `n` is the number of elements in the input array `nums`. +This implementation provides a solution to the "Permutations" problem in Java. It generates all possible permutations of the given array of distinct integers using backtracking. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0048_rotate_image/readme.md b/src/main/java/g0001_0100/s0048_rotate_image/readme.md index 87cbdf0b..0505093c 100644 --- a/src/main/java/g0001_0100/s0048_rotate_image/readme.md +++ b/src/main/java/g0001_0100/s0048_rotate_image/readme.md @@ -44,43 +44,48 @@ You have to rotate the image [**in-place**](https://en.wikipedia.org/wiki/In-pla * `1 <= n <= 20` * `-1000 <= matrix[i][j] <= 1000` -## Solution +To solve the "Rotate Image" problem in Java with a `Solution` class, we can follow these steps: + +1. Define a `Solution` class. +2. Define a method named `rotate` that takes a 2D array `matrix` representing an image as input and rotates the image by 90 degrees clockwise. +3. Determine the number of layers in the matrix, which is equal to half of the matrix's size. +4. Iterate through each layer from outer to inner layers. +5. For each layer: + - Iterate through each element in the current layer. + - Swap the elements of the current layer in a clockwise manner. +6. Return the rotated matrix. + +Here's the implementation: ```java public class Solution { public void rotate(int[][] matrix) { int n = matrix.length; - for (int i = 0; i < n / 2; i++) { - for (int j = i; j < n - i - 1; j++) { - int[][] pos = - new int[][] { - {i, j}, {j, n - 1 - i}, {n - 1 - i, n - 1 - j}, {n - 1 - j, i} - }; - int t = matrix[pos[0][0]][pos[0][1]]; - for (int k = 1; k < pos.length; k++) { - int temp = matrix[pos[k][0]][pos[k][1]]; - matrix[pos[k][0]][pos[k][1]] = t; - t = temp; - } - matrix[pos[0][0]][pos[0][1]] = t; + int layers = n / 2; + + for (int layer = 0; layer < layers; layer++) { + int first = layer; + int last = n - 1 - layer; + + for (int i = first; i < last; i++) { + int offset = i - first; + int top = matrix[first][i]; + + // Move left to top + matrix[first][i] = matrix[last - offset][first]; + + // Move bottom to left + matrix[last - offset][first] = matrix[last][last - offset]; + + // Move right to bottom + matrix[last][last - offset] = matrix[i][last]; + + // Move top to right + matrix[i][last] = top; } } } } ``` -**Time Complexity (Big O Time):** - -1. The program uses two nested loops, where `i` and `j` iterate from 0 to `n/2-1`, where `n` is the number of rows (and columns) in the square matrix. - -2. The innermost loop, represented by `k`, runs four times for each element (corner) in the matrix. The innermost loop contains constant-time operations. - -3. Therefore, the time complexity of the program is O(n^2), where `n` is the number of rows (and columns) in the square matrix. This is because we perform constant-time operations for each element in the matrix. - -**Space Complexity (Big O Space):** - -1. The space complexity of the program is O(1), which means it uses a constant amount of additional space regardless of the size of the input matrix. - -2. The program uses a few integer variables (`n`, `i`, `j`, `k`, `t`, `temp`, `pos` array), but the space required for these variables remains constant as the input matrix size increases. The space complexity does not depend on the size of the input matrix. - -In summary, the time complexity of the provided program is O(n^2), and the space complexity is O(1), where `n` is the number of rows (and columns) in the square matrix. +This implementation provides a solution to the "Rotate Image" problem in Java. It rotates the given 2D matrix representing an image by 90 degrees clockwise in-place. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0049_group_anagrams/readme.md b/src/main/java/g0001_0100/s0049_group_anagrams/readme.md index 92ab3b73..89f45712 100644 --- a/src/main/java/g0001_0100/s0049_group_anagrams/readme.md +++ b/src/main/java/g0001_0100/s0049_group_anagrams/readme.md @@ -33,54 +33,50 @@ An **Anagram** is a word or phrase formed by rearranging the letters of a differ * `0 <= strs[i].length <= 100` * `strs[i]` consists of lowercase English letters. -## Solution +To solve the "Group Anagrams" problem in Java with the Solution class, follow these steps: + +1. Define a method `groupAnagrams` in the `Solution` class that takes an array of strings `strs` as input and returns a list of lists of strings. +2. Initialize an empty HashMap to store the groups of anagrams. The key will be the sorted string, and the value will be a list of strings. +3. Iterate through each string `str` in the input array `strs`. +4. Sort the characters of the current string `str` to create a key for the HashMap. +5. Check if the sorted string exists as a key in the HashMap: + - If it does, add the original string `str` to the corresponding list of strings. + - If it doesn't, create a new entry in the HashMap with the sorted string as the key and a new list containing `str` as the value. +6. After iterating through all strings, return the values of the HashMap as the result. + +Here's the implementation of the `groupAnagrams` method in Java: ```java -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; -public class Solution { +class Solution { public List> groupAnagrams(String[] strs) { - Map> hm = new HashMap<>(); - for (String s : strs) { - char[] ch = s.toCharArray(); - Arrays.sort(ch); - String temp = new String(ch); - hm.computeIfAbsent(temp, k -> new ArrayList<>()); - hm.get(temp).add(s); + // Initialize a HashMap to store the groups of anagrams + Map> anagramGroups = new HashMap<>(); + + // Iterate through each string in the input array + for (String str : strs) { + // Sort the characters of the current string + char[] chars = str.toCharArray(); + Arrays.sort(chars); + String sortedStr = new String(chars); + + // Check if the sorted string exists as a key in the HashMap + if (anagramGroups.containsKey(sortedStr)) { + // If it does, add the original string to the corresponding list + anagramGroups.get(sortedStr).add(str); + } else { + // If it doesn't, create a new entry in the HashMap + List group = new ArrayList<>(); + group.add(str); + anagramGroups.put(sortedStr, group); + } } - return (new ArrayList<>(hm.values())); + + // Return the values of the HashMap as the result + return new ArrayList<>(anagramGroups.values()); } } ``` -**Time Complexity (Big O Time):** - -1. The program uses a loop to iterate through each string in the `strs` array. Let's assume there are 'n' strings in the array. - -2. For each string, it converts the string into a character array, sorts the character array, and converts it back into a string. This sorting operation takes O(k log k) time, where 'k' is the length of the longest string in the array. - -3. After sorting, it checks if the sorted string exists as a key in the `hm` (HashMap). This operation is typically O(1) on average because it involves a hash table lookup. - -4. If the key doesn't exist, it creates a new key-value pair in the `hm` HashMap. This is an O(1) operation in the average case. - -5. Finally, it adds the original string to the list associated with the sorted string. Adding an element to a list is O(1) on average. - -6. Overall, for each of the 'n' strings in the array, the program performs O(k log k) sorting operations and O(1) HashMap operations. - -7. Therefore, the overall time complexity of the program is O(n * k log k), where 'n' is the number of strings in the array, and 'k' is the length of the longest string. - -**Space Complexity (Big O Space):** - -1. The space complexity of the program is determined by the additional data structures used. These include the `hm` HashMap and the lists that store grouped anagrams. - -2. The space required for the `hm` HashMap depends on the number of unique sorted strings, which is typically less than or equal to 'n' (the number of input strings). - -3. The space required for the lists that store grouped anagrams is also proportional to 'n' because each input string is associated with one of these lists. - -4. Therefore, the overall space complexity of the program is O(n), where 'n' is the number of strings in the input array `strs`. - -In summary, the time complexity of the provided program is O(n * k log k), where 'n' is the number of strings, and 'k' is the length of the longest string. The space complexity is O(n). +This implementation ensures that all anagrams are grouped together efficiently using a HashMap. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0051_n_queens/readme.md b/src/main/java/g0001_0100/s0051_n_queens/readme.md index 0c9078c6..70c77229 100644 --- a/src/main/java/g0001_0100/s0051_n_queens/readme.md +++ b/src/main/java/g0001_0100/s0051_n_queens/readme.md @@ -31,85 +31,81 @@ Each solution contains a distinct board configuration of the n-queens' placement * `1 <= n <= 9` -## Solution +To solve the "N-Queens" problem in Java with the Solution class, follow these steps: + +1. Define a method `solveNQueens` in the `Solution` class that takes an integer `n` as input and returns a list of lists of strings. +2. Initialize a board represented as a 2D character array of size `n x n`. Initialize all cells to `'.'`, indicating an empty space. +3. Define a recursive backtracking function `backtrack` to explore all possible configurations of queens on the board. +4. In the `backtrack` function: + - Base case: If the current row index `row` is equal to `n`, it means we have successfully placed `n` queens on the board. Add the current board configuration to the result. + - Iterate through each column index `col` from `0` to `n - 1`: + - Check if it's safe to place a queen at position `(row, col)` by calling a helper function `isSafe`. + - If it's safe, place a queen at position `(row, col)` on the board, mark it as `'Q'`. + - Recur to the next row by calling `backtrack(row + 1)`. + - Backtrack: After exploring all possibilities, remove the queen from position `(row, col)` by marking it as `'.'`. +5. In the `solveNQueens` method, initialize an empty list `result` to store the solutions. +6. Call the `backtrack` function with initial parameters `0` for the row index. +7. Return the `result` list containing all distinct solutions. + +Here's the implementation of the `solveNQueens` method in Java: ```java -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; -public class Solution { +class Solution { public List> solveNQueens(int n) { - boolean[] pos = new boolean[n + 2 * n - 1 + 2 * n - 1]; - int[] pos2 = new int[n]; - List> ans = new ArrayList<>(); - helper(n, 0, pos, pos2, ans); - return ans; + List> result = new ArrayList<>(); + char[][] board = new char[n][n]; + for (int i = 0; i < n; i++) { + Arrays.fill(board[i], '.'); + } + backtrack(board, 0, result); + return result; } - - private void helper(int n, int row, boolean[] pos, int[] pos2, List> ans) { + + private void backtrack(char[][] board, int row, List> result) { + int n = board.length; if (row == n) { - construct(n, pos2, ans); + result.add(constructBoard(board)); return; } - for (int i = 0; i < n; i++) { - int index = n + 2 * n - 1 + n - 1 + i - row; - if (pos[i] || pos[n + i + row] || pos[index]) { - continue; + for (int col = 0; col < n; col++) { + if (isSafe(board, row, col)) { + board[row][col] = 'Q'; + backtrack(board, row + 1, result); + board[row][col] = '.'; } - pos[i] = true; - pos[n + i + row] = true; - pos[index] = true; - pos2[row] = i; - helper(n, row + 1, pos, pos2, ans); - pos[i] = false; - pos[n + i + row] = false; - pos[index] = false; } } - - private void construct(int n, int[] pos, List> ans) { - List sol = new ArrayList<>(); - for (int r = 0; r < n; r++) { - char[] queenRow = new char[n]; - Arrays.fill(queenRow, '.'); - queenRow[pos[r]] = 'Q'; - sol.add(new String(queenRow)); + + private boolean isSafe(char[][] board, int row, int col) { + int n = board.length; + for (int i = 0; i < row; i++) { + if (board[i][col] == 'Q') { + return false; + } } - ans.add(sol); + for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) { + if (board[i][j] == 'Q') { + return false; + } + } + for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) { + if (board[i][j] == 'Q') { + return false; + } + } + return true; + } + + private List constructBoard(char[][] board) { + List solution = new ArrayList<>(); + for (char[] row : board) { + solution.add(new String(row)); + } + return solution; } } ``` -**Time Complexity (Big O Time):** - -1. The program uses a recursive backtracking algorithm to explore all possible solutions. It places queens row by row, and for each row, it iterates through the columns to find a valid placement. - -2. The main recursive function `helper` is called for each row, and for each row, it iterates through the columns. In the worst case, this results in exploring all possible combinations of queen placements. - -3. For each queen placement, it checks whether it's valid based on the positions of previously placed queens. The checks include validating the columns, diagonals, and anti-diagonals. - -4. The time complexity of the recursive algorithm can be analyzed as follows: - - For the first row, there are N possibilities. - - For the second row, there are N-2 possibilities (two columns in the same column as the first queen are not allowed). - - For the third row, there are N-4 possibilities (four columns are eliminated due to diagonal and anti-diagonal constraints), and so on. - -5. The worst-case time complexity of exploring all possible combinations is exponential, and it's typically represented as O(N!) for the N-Queens problem, where N is the size of the chessboard (number of rows and columns). - -6. Additionally, constructing the solution in the `construct` method takes O(N) time for each solution. - -7. Therefore, the overall time complexity is dominated by the number of recursive calls and is O(N!). - -**Space Complexity (Big O Space):** - -1. The space complexity is determined by the additional data structures used in the program. - -2. The `pos` boolean array of size `n + 2 * n - 1 + 2 * n - 1` is used to keep track of occupied columns, diagonals, and anti-diagonals. It grows with the size of the chessboard but is not dependent on the number of solutions. Therefore, its space complexity is O(N). - -3. The `pos2` integer array of size `n` is used to keep track of the column positions of queens in each row. Its space complexity is O(N). - -4. The `ans` list of lists stores the solutions, and its space complexity depends on the number of solutions. In the worst case, there can be N! solutions. - -5. Therefore, the overall space complexity is dominated by the storage of solutions and is O(N!). - -In summary, the time complexity of the provided program is O(N!) due to the combinatorial nature of the N-Queens problem, and the space complexity is O(N) due to the additional data structures used to track queen placements and store solutions. +This implementation efficiently finds all distinct solutions to the N-Queens problem using backtracking. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0053_maximum_subarray/readme.md b/src/main/java/g0001_0100/s0053_maximum_subarray/readme.md index f97f2c58..1ac42545 100644 --- a/src/main/java/g0001_0100/s0053_maximum_subarray/readme.md +++ b/src/main/java/g0001_0100/s0053_maximum_subarray/readme.md @@ -36,41 +36,32 @@ A **subarray** is a **contiguous** part of an array. **Follow up:** If you have figured out the `O(n)` solution, try coding another solution using the **divide and conquer** approach, which is more subtle. -## Solution +To solve the "Maximum Subarray" problem in Java with the Solution class, follow these steps: + +1. Define a method `maxSubArray` in the `Solution` class that takes an integer array `nums` as input and returns an integer representing the largest sum of a contiguous subarray. +2. Initialize two variables `maxSum` and `currentSum` to store the maximum sum found so far and the sum of the current subarray being considered, respectively. Set both to the value of the first element in `nums`. +3. Iterate through the array `nums` from index `1` to `nums.length - 1`: + - Update `currentSum` as the maximum of the current element and the sum of the current element plus `currentSum`. + - Update `maxSum` as the maximum of `maxSum` and `currentSum`. +4. After iterating through all elements in `nums`, return `maxSum`. + +Here's the implementation of the `maxSubArray` method in Java: ```java -public class Solution { +class Solution { public int maxSubArray(int[] nums) { - int maxi = Integer.MIN_VALUE; - int sum = 0; - for (int num : nums) { - // calculating sub-array sum - sum += num; - maxi = Math.max(sum, maxi); - if (sum < 0) { - // there is no point to carry a -ve subarray sum. hence setting to 0 - sum = 0; - } + if (nums == null || nums.length == 0) { + return 0; + } + int maxSum = nums[0]; + int currentSum = nums[0]; + for (int i = 1; i < nums.length; i++) { + currentSum = Math.max(nums[i], currentSum + nums[i]); + maxSum = Math.max(maxSum, currentSum); } - return maxi; + return maxSum; } } ``` -**Time Complexity (Big O Time):** - -1. The program uses a single loop to iterate through the elements of the `nums` array. Let's assume there are 'n' elements in the array. - -2. In each iteration of the loop, the program performs constant time operations such as addition, comparison, and calls to `Math.max`. - -3. Therefore, the time complexity of the program is O(n), where 'n' is the number of elements in the input array `nums`. - -**Space Complexity (Big O Space):** - -1. The space complexity of the program is O(1), which means it uses a constant amount of additional space regardless of the size of the input array. - -2. The program uses a few integer variables (`maxi` and `sum`) to keep track of the maximum subarray sum and the current subarray sum, respectively. These variables require constant space. - -3. The space complexity does not depend on the size of the input array `nums`. - -In summary, the time complexity of the provided program is O(n), and the space complexity is O(1), where 'n' is the number of elements in the input array `nums`. The program efficiently finds the maximum subarray sum using a single pass through the array. +This implementation efficiently finds the largest sum of a contiguous subarray in the given array `nums` using the Kadane's algorithm, which has a time complexity of O(n). \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0055_jump_game/readme.md b/src/main/java/g0001_0100/s0055_jump_game/readme.md index 5dfc1c26..530fa45e 100644 --- a/src/main/java/g0001_0100/s0055_jump_game/readme.md +++ b/src/main/java/g0001_0100/s0055_jump_game/readme.md @@ -30,65 +30,36 @@ Return `true` _if you can reach the last index, or_ `false` _otherwise_. * 1 <= nums.length <= 104 * 0 <= nums[i] <= 105 -## Solution +To solve the "Jump Game" problem in Java with the Solution class, follow these steps: + +1. Define a method `canJump` in the `Solution` class that takes an integer array `nums` as input and returns a boolean indicating whether it's possible to reach the last index. +2. Initialize a variable `maxReach` to keep track of the maximum index that can be reached. +3. Iterate through the array `nums` from index `0` to `nums.length - 1`: + - Check if the current index `i` is greater than `maxReach`. If it is, return `false` as it's not possible to reach the last index. + - Update `maxReach` as the maximum of `maxReach` and `i + nums[i]`, which represents the furthest index that can be reached from the current position. +4. After iterating through all elements in `nums`, return `true` as it's possible to reach the last index. + +Here's the implementation of the `canJump` method in Java: ```java -public class Solution { +class Solution { public boolean canJump(int[] nums) { - int sz = nums.length; - // we set 1 so it won't break on the first iteration - int tmp = 1; - for (int i = 0; i < sz; i++) { - // we always deduct tmp for every iteration - tmp--; - if (tmp < 0) { - // if from previous iteration tmp is already 0, it will be <0 here - // leading to false value + if (nums == null || nums.length == 0) { + return false; + } + int maxReach = 0; + for (int i = 0; i < nums.length; i++) { + if (i > maxReach) { return false; } - // we get the maximum value because this value is supposed - // to be our iterator, if both values are 0, then the next - // iteration we will return false - // if either both or one of them are not 0 then we will keep doing this and check. - - // We can stop the whole iteration with this condition. without this condition the code - // runs in 2ms 79.6%, adding this condition improves the performance into 1ms 100% - // because if the test case jump value is quite large, instead of just iterate, we can - // just check using this condition - // example: [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -> we can just jump to the end without - // iterating whole array - tmp = Math.max(tmp, nums[i]); - if (i + tmp >= sz - 1) { + maxReach = Math.max(maxReach, i + nums[i]); + if (maxReach >= nums.length - 1) { return true; } } - // we can just return true at the end, because if tmp is 0 on previous - // iteration, - // even though the next iteration index is the last one, it will return false under the - // tmp<0 condition - return true; + return false; } } ``` -**Time Complexity (Big O Time):** - -1. The program uses a single loop that iterates through the elements of the `nums` array. Let's assume there are 'n' elements in the array. - -2. In each iteration of the loop, the program performs constant time operations such as subtraction, comparison, and taking the maximum value. - -3. The loop iterates until the end of the array or until it determines that it's not possible to jump further. - -4. In the worst case, the loop may iterate through all 'n' elements of the array. - -5. Therefore, the time complexity of the program is O(n), where 'n' is the number of elements in the input array `nums`. - -**Space Complexity (Big O Space):** - -1. The space complexity of the program is O(1), which means it uses a constant amount of additional space regardless of the size of the input array. - -2. The program uses a few integer variables (`sz` and `tmp`) to keep track of the array size and the jump value. These variables require constant space. - -3. The space complexity does not depend on the size of the input array `nums`. - -In summary, the time complexity of the provided program is O(n), and the space complexity is O(1), where 'n' is the number of elements in the input array `nums`. The program efficiently checks if it's possible to jump to the end of the array using a single pass through the array. +This implementation efficiently determines whether it's possible to reach the last index in the given array `nums` using a greedy approach, with a time complexity of O(n). \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0056_merge_intervals/readme.md b/src/main/java/g0001_0100/s0056_merge_intervals/readme.md index b81dc7a9..aac9046e 100644 --- a/src/main/java/g0001_0100/s0056_merge_intervals/readme.md +++ b/src/main/java/g0001_0100/s0056_merge_intervals/readme.md @@ -29,52 +29,35 @@ Given an array of `intervals` where intervals[i] = [starti, end * `intervals[i].length == 2` * 0 <= starti <= endi <= 104 -## Solution +To solve the "Merge Intervals" problem in Java with the Solution class, follow these steps: + +1. Define a method `merge` in the `Solution` class that takes an array of integer arrays `intervals` as input and returns an array of the non-overlapping intervals that cover all the intervals in the input. +2. Sort the intervals based on the start times. +3. Initialize an ArrayList to store the merged intervals. +4. Iterate through the sorted intervals: + - If the list of merged intervals is empty or the current interval's start time is greater than the end time of the last merged interval, add the current interval to the list of merged intervals. + - Otherwise, merge the current interval with the last merged interval by updating its end time if needed. +5. Convert the ArrayList of merged intervals into an array and return it as the result. + +Here's the implementation of the `merge` method in Java: ```java -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; -public class Solution { +class Solution { public int[][] merge(int[][] intervals) { Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0])); - List list = new ArrayList<>(); - int[] current = intervals[0]; - list.add(current); - for (int[] next : intervals) { - if (current[1] >= next[0]) { - current[1] = Math.max(current[1], next[1]); + List merged = new ArrayList<>(); + for (int[] interval : intervals) { + if (merged.isEmpty() || interval[0] > merged.get(merged.size() - 1)[1]) { + merged.add(interval); } else { - current = next; - list.add(current); + merged.get(merged.size() - 1)[1] = Math.max(merged.get(merged.size() - 1)[1], interval[1]); } } - return list.toArray(new int[list.size()][]); + return merged.toArray(new int[merged.size()][]); } } ``` -**Time Complexity (Big O Time):** - -1. The program first sorts the `intervals` array based on the start values of each interval. Sorting takes O(n log n) time, where 'n' is the number of intervals in the array. - -2. After sorting, it iterates through the sorted intervals exactly once. - -3. In the loop, it performs constant time operations for each interval, such as comparisons and updates. - -4. Therefore, the overall time complexity is dominated by the sorting step and is O(n log n), where 'n' is the number of intervals in the input array `intervals`. - -**Space Complexity (Big O Space):** - -1. The space complexity of the program is determined by the additional data structures used. - -2. It uses a `List` called `list` to store the merged intervals. In the worst case, where there are no overlapping intervals, this list could contain all 'n' intervals. Therefore, the space complexity of this list is O(n). - -3. The `current` array of size 2 is used to keep track of the current merged interval. This array requires constant space. - -4. The `int[][]` array returned at the end of the program is created based on the size of the `list`. In the worst case, it would have 'n' subarrays, each with two elements. - -5. Therefore, the overall space complexity is dominated by the `list` and is O(n). - -In summary, the time complexity of the provided program is O(n log n) due to the sorting step, and the space complexity is O(n) due to the `list` used to store merged intervals. The program efficiently merges overlapping intervals and returns a new array of merged intervals. +This implementation efficiently merges overlapping intervals in the given array `intervals` using sorting and iteration, with a time complexity of O(n log n) due to sorting. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0062_unique_paths/readme.md b/src/main/java/g0001_0100/s0062_unique_paths/readme.md index cc7bc0cc..65b5665e 100644 --- a/src/main/java/g0001_0100/s0062_unique_paths/readme.md +++ b/src/main/java/g0001_0100/s0062_unique_paths/readme.md @@ -49,42 +49,35 @@ How many possible unique paths are there? * `1 <= m, n <= 100` * It's guaranteed that the answer will be less than or equal to 2 * 109. -## Solution +To solve the "Unique Paths" problem in Java with the Solution class, follow these steps: + +1. Define a method `uniquePaths` in the `Solution` class that takes two integers `m` and `n` as input and returns the number of unique paths from the top-left corner to the bottom-right corner of an `m x n` grid. +2. Initialize a 2D array `dp` of size `m x n` to store the number of unique paths for each position in the grid. +3. Initialize the first row and first column of `dp` to 1 since there is only one way to reach any position in the first row or column (by moving only right or down). +4. Iterate over each position `(i, j)` in the grid, starting from the second row and second column: + - Update `dp[i][j]` by adding the number of unique paths from the cell above `(i-1, j)` and the cell to the left `(i, j-1)`. +5. Return the value of `dp[m-1][n-1]`, which represents the number of unique paths to reach the bottom-right corner of the grid. + +Here's the implementation of the `uniquePaths` method in Java: ```java -public class Solution { +class Solution { public int uniquePaths(int m, int n) { int[][] dp = new int[m][n]; for (int i = 0; i < m; i++) { - dp[i][0] = 1; + dp[i][0] = 1; // Initialize first column to 1 } for (int j = 0; j < n; j++) { - dp[0][j] = 1; + dp[0][j] = 1; // Initialize first row to 1 } for (int i = 1; i < m; i++) { for (int j = 1; j < n; j++) { - dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; + dp[i][j] = dp[i-1][j] + dp[i][j-1]; // Calculate number of paths for current cell } } - return dp[m - 1][n - 1]; + return dp[m-1][n-1]; // Return number of unique paths for bottom-right corner } } ``` -**Time Complexity (Big O Time):** - -1. The program uses a dynamic programming approach to fill in a 2D array `dp` of size `m`x`n` with values. - -2. The first two loops (two separate loops, one for setting the values in the first column and one for setting the values in the first row) each run in O(max(m, n)) time because they iterate through the entire first column and first row. - -3. The nested loops, which fill in the remaining cells of the `dp` array, run in O(m * n) time because they iterate through all the rows and columns. - -4. Therefore, the overall time complexity of the program is O(m * n), where 'm' is the number of rows, and 'n' is the number of columns in the grid. - -**Space Complexity (Big O Space):** - -1. The program uses a 2D array `dp` of size `m`x`n` to store the intermediate results. Therefore, the space complexity is O(m * n), where 'm' is the number of rows, and 'n' is the number of columns in the grid. - -2. The space complexity is dominated by the `dp` array, and it does not depend on the input values of 'm' and 'n' but only on the grid size. - -In summary, the time complexity of the provided program is O(m * n), and the space complexity is also O(m * n), where 'm' is the number of rows, and 'n' is the number of columns in the grid. The program efficiently calculates the number of unique paths in the grid using dynamic programming. +This implementation efficiently calculates the number of unique paths using dynamic programming, with a time complexity of O(m * n) and a space complexity of O(m * n). \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0064_minimum_path_sum/readme.md b/src/main/java/g0001_0100/s0064_minimum_path_sum/readme.md index 987cbaa1..a291915b 100644 --- a/src/main/java/g0001_0100/s0064_minimum_path_sum/readme.md +++ b/src/main/java/g0001_0100/s0064_minimum_path_sum/readme.md @@ -32,53 +32,43 @@ Given a `m x n` `grid` filled with non-negative numbers, find a path from top le * `1 <= m, n <= 200` * `0 <= grid[i][j] <= 100` -## Solution +To solve the "Minimum Path Sum" problem in Java with the Solution class, follow these steps: + +1. Define a method `minPathSum` in the `Solution` class that takes a 2D grid of non-negative numbers as input and returns the minimum sum of all numbers along the path from the top-left corner to the bottom-right corner of the grid. +2. Initialize a 2D array `dp` of size `m x n`, where `dp[i][j]` represents the minimum sum of the path from the top-left corner to position `(i, j)` in the grid. +3. Initialize `dp[0][0]` to the value of the top-left cell in the grid. +4. Initialize the first row and first column of `dp` based on the grid values and the previous cells in the same row or column. +5. Iterate over each position `(i, j)` in the grid, starting from the second row and second column: + - Update `dp[i][j]` by adding the current grid value at `(i, j)` to the minimum of the values of the previous cells `(i-1, j)` and `(i, j-1)` in `dp`. +6. Return `dp[m-1][n-1]`, which represents the minimum path sum from the top-left corner to the bottom-right corner of the grid. + +Here's the implementation of the `minPathSum` method in Java: ```java -public class Solution { +class Solution { public int minPathSum(int[][] grid) { - if (grid.length == 1 && grid[0].length == 1) { - return grid[0][0]; + int m = grid.length; + int n = grid[0].length; + int[][] dp = new int[m][n]; + + dp[0][0] = grid[0][0]; + // Initialize first row + for (int j = 1; j < n; j++) { + dp[0][j] = dp[0][j-1] + grid[0][j]; } - int[][] dm = new int[grid.length][grid[0].length]; - int s = 0; - for (int r = grid.length - 1; r >= 0; r--) { - dm[r][grid[0].length - 1] = grid[r][grid[0].length - 1] + s; - s += grid[r][grid[0].length - 1]; + // Initialize first column + for (int i = 1; i < m; i++) { + dp[i][0] = dp[i-1][0] + grid[i][0]; } - s = 0; - for (int c = grid[0].length - 1; c >= 0; c--) { - dm[grid.length - 1][c] = grid[grid.length - 1][c] + s; - s += grid[grid.length - 1][c]; + // Fill in the rest of the dp array + for (int i = 1; i < m; i++) { + for (int j = 1; j < n; j++) { + dp[i][j] = grid[i][j] + Math.min(dp[i-1][j], dp[i][j-1]); + } } - return recur(grid, dm, 0, 0); - } - - private int recur(int[][] grid, int[][] dm, int r, int c) { - if (dm[r][c] == 0 && r != grid.length - 1 && c != grid[0].length - 1) { - dm[r][c] = grid[r][c] + Math.min(recur(grid, dm, r + 1, c), recur(grid, dm, r, c + 1)); - } - return dm[r][c]; + return dp[m-1][n-1]; } } ``` -**Time Complexity (Big O Time):** - -1. The program uses dynamic programming to fill in a 2D array `dm` of size `m`x`n`, where 'm' is the number of rows and 'n' is the number of columns in the grid. - -2. The first two loops (one for the last row and one for the last column) each run in O(max(m, n)) time because they iterate through the entire last row and last column. - -3. The `recur` method is called recursively for each cell in the grid, but it uses memoization (`dm` array) to avoid redundant calculations. In the worst case, it recursively computes the minimum path sum for all cells in the grid. - -4. Therefore, the overall time complexity of the program is O(m * n), where 'm' is the number of rows, and 'n' is the number of columns in the grid. - -**Space Complexity (Big O Space):** - -1. The program uses a 2D array `dm` of size `m`x`n` to store the intermediate results. Therefore, the space complexity is O(m * n), where 'm' is the number of rows, and 'n' is the number of columns in the grid. - -2. The space complexity is dominated by the `dm` array, and it does not depend on the input values of 'm' and 'n' but only on the grid size. - -3. Additionally, the program uses some integer variables and constants, but their space usage is constant and does not depend on the grid size. - -In summary, the time complexity of the provided program is O(m * n), and the space complexity is also O(m * n), where 'm' is the number of rows, and 'n' is the number of columns in the grid. The program efficiently calculates the minimum path sum in the grid using dynamic programming with memoization. +This implementation efficiently calculates the minimum path sum using dynamic programming, with a time complexity of O(m * n) and a space complexity of O(m * n). \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0070_climbing_stairs/readme.md b/src/main/java/g0001_0100/s0070_climbing_stairs/readme.md index 0b81705e..98229dbf 100644 --- a/src/main/java/g0001_0100/s0070_climbing_stairs/readme.md +++ b/src/main/java/g0001_0100/s0070_climbing_stairs/readme.md @@ -29,50 +29,34 @@ Each time you can either climb `1` or `2` steps. In how many distinct ways can y * `1 <= n <= 45` -## Solution +To solve the "Climbing Stairs" problem in Java with the Solution class, follow these steps: + +1. Define a method `climbStairs` in the `Solution` class that takes an integer `n` as input and returns the number of distinct ways to climb to the top of the staircase with `n` steps. +2. Initialize an array `dp` of size `n+1` to store the number of distinct ways to reach each step. +3. Set `dp[0] = 1` and `dp[1] = 1` since there is only one way to reach the first and second steps. +4. Iterate over the steps from `2` to `n`: + - At each step `i`, the number of distinct ways to reach step `i` is the sum of the number of ways to reach steps `i-1` and `i-2`. + - Store this sum in `dp[i]`. +5. Return `dp[n]`, which represents the number of distinct ways to climb to the top of the staircase with `n` steps. + +Here's the implementation of the `climbStairs` method in Java: ```java -public class Solution { +class Solution { public int climbStairs(int n) { - if (n < 2) { - return n; + if (n == 1) return 1; + + int[] dp = new int[n + 1]; + dp[0] = 1; + dp[1] = 1; + + for (int i = 2; i <= n; i++) { + dp[i] = dp[i - 1] + dp[i - 2]; } - int[] cache = new int[n]; - // creating a cache or DP to store the result - // so that we dont have to iterate multiple times - // for the same values; - - // for 0 and 1 the result array i.e cache values would be 1 and 2 - // in loop we are just getting ith values i.e 5th step values from - // i-1 and i-2 which are 4th step and 3rd step values. - cache[0] = 1; - cache[1] = 2; - for (int i = 2; i < n; i++) { - cache[i] = cache[i - 1] + cache[i - 2]; - } - return cache[n - 1]; + + return dp[n]; } } ``` -**Time Complexity (Big O Time):** - -1. The program uses dynamic programming with a loop that runs from 2 to `n-1` to fill in the `cache` array. - -2. The loop iterates through all steps from 2 to `n-1`, and for each step `i`, it calculates the number of distinct ways by summing the values from the previous two steps (`cache[i-1]` and `cache[i-2]`). - -3. Therefore, the loop runs in O(n) time because it iterates through all `n` steps once. - -4. The other operations in the program, such as array assignments and comparisons, are constant time operations and do not depend on the input value `n`. - -5. Overall, the time complexity of the program is O(n), where 'n' is the number of steps in the staircase. - -**Space Complexity (Big O Space):** - -1. The program uses an integer array `cache` of size `n` to store the intermediate results of the number of distinct ways to climb each step. - -2. Therefore, the space complexity is O(n) because the space usage is directly proportional to the input value `n`. - -3. The space complexity is dominated by the `cache` array, and it scales linearly with the size of the input staircase. - -In summary, the time complexity of the provided program is O(n), and the space complexity is also O(n), where 'n' is the number of steps in the staircase. The program efficiently calculates the number of distinct ways to climb the staircase using dynamic programming with memoization. +This implementation efficiently calculates the number of distinct ways to climb the stairs using dynamic programming, with a time complexity of O(n) and a space complexity of O(n). \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0072_edit_distance/readme.md b/src/main/java/g0001_0100/s0072_edit_distance/readme.md index e0eb79ab..8caea8f2 100644 --- a/src/main/java/g0001_0100/s0072_edit_distance/readme.md +++ b/src/main/java/g0001_0100/s0072_edit_distance/readme.md @@ -34,54 +34,51 @@ You have the following three operations permitted on a word: * `0 <= word1.length, word2.length <= 500` * `word1` and `word2` consist of lowercase English letters. -## Solution +To solve the "Edit Distance" problem in Java with the Solution class, follow these steps: + +1. Define a method `minDistance` in the `Solution` class that takes two strings `word1` and `word2` as input and returns the minimum number of operations required to convert `word1` to `word2`. +2. Initialize a 2D array `dp` of size `(m+1) x (n+1)`, where `m` is the length of `word1` and `n` is the length of `word2`. +3. Set `dp[i][0] = i` for all `i` from `0` to `m`, as the minimum number of operations to convert a string of length `i` to an empty string is `i` deletions. +4. Set `dp[0][j] = j` for all `j` from `0` to `n`, as the minimum number of operations to convert an empty string to a string of length `j` is `j` insertions. +5. Iterate over the characters of `word1` and `word2`: + - If `word1.charAt(i-1)` is equal to `word2.charAt(j-1)`, set `dp[i][j] = dp[i-1][j-1]`, as no operation is required to match these characters. + - Otherwise, set `dp[i][j]` to the minimum of the following three options: + - `dp[i-1][j] + 1`: Delete the character at position `i` from `word1`. + - `dp[i][j-1] + 1`: Insert the character at position `j` from `word2` into `word1`. + - `dp[i-1][j-1] + 1`: Replace the character at position `i` in `word1` with the character at position `j` in `word2`. +6. Return `dp[m][n]`, which represents the minimum number of operations required to convert `word1` to `word2`. + +Here's the implementation of the `minDistance` method in Java: ```java -@SuppressWarnings("java:S2234") -public class Solution { - public int minDistance(String w1, String w2) { - int n1 = w1.length(); - int n2 = w2.length(); - if (n2 > n1) { - return minDistance(w2, w1); +class Solution { + public int minDistance(String word1, String word2) { + int m = word1.length(); + int n = word2.length(); + + int[][] dp = new int[m + 1][n + 1]; + + for (int i = 0; i <= m; i++) { + dp[i][0] = i; } - int[] dp = new int[n2 + 1]; - for (int j = 0; j <= n2; j++) { - dp[j] = j; + + for (int j = 0; j <= n; j++) { + dp[0][j] = j; } - for (int i = 1; i <= n1; i++) { - int pre = dp[0]; - dp[0] = i; - for (int j = 1; j <= n2; j++) { - int tmp = dp[j]; - dp[j] = - w1.charAt(i - 1) != w2.charAt(j - 1) - ? 1 + Math.min(pre, Math.min(dp[j], dp[j - 1])) - : pre; - pre = tmp; + + for (int i = 1; i <= m; i++) { + for (int j = 1; j <= n; j++) { + if (word1.charAt(i - 1) == word2.charAt(j - 1)) { + dp[i][j] = dp[i - 1][j - 1]; + } else { + dp[i][j] = Math.min(dp[i - 1][j], Math.min(dp[i][j - 1], dp[i - 1][j - 1])) + 1; + } } } - return dp[n2]; + + return dp[m][n]; } } ``` -**Time Complexity (Big O Time):** - -1. The program uses dynamic programming with a nested loop structure. The outer loop runs from 1 to `n1`, and the inner loop runs from 1 to `n2`, where `n1` and `n2` are the lengths of the input words `w1` and `w2`. - -2. Inside the inner loop, there are constant-time operations like array indexing, character comparisons, and mathematical operations (addition and minimum calculations). These operations do not depend on the size of the input words. - -3. Therefore, the dominant factor in the time complexity is the nested loops. The outer loop runs for `n1` iterations, and the inner loop runs for `n2` iterations. As a result, the time complexity is O(n1 * n2). - -4. In the worst case, `n1` and `n2` can be equal to the lengths of the input words, so the time complexity can be represented as O(n^2), where 'n' is the maximum of the lengths of `w1` and `w2`. - -**Space Complexity (Big O Space):** - -1. The program uses an integer array `dp` of size `n2 + 1`, where `n2` is the length of the shorter word `w2`. Additionally, there are some integer variables used for temporary storage. - -2. Therefore, the space complexity is O(n2) because the space usage is directly proportional to the length of the shorter input word `w2`. - -3. The space complexity does not depend on the length of the longer word `w1` because the program is designed to handle the shorter word as the outer loop variable. - -In summary, the time complexity of the provided program is O(n^2), where 'n' is the maximum of the lengths of `w1` and `w2`. The space complexity is O(n2), where `n2` is the length of the shorter word `w2`. The program efficiently calculates the minimum edit distance between two words using dynamic programming. +This implementation efficiently calculates the minimum edit distance between two strings using dynamic programming, with a time complexity of O(m * n) and a space complexity of O(m * n), where m is the length of `word1` and n is the length of `word2`. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0073_set_matrix_zeroes/readme.md b/src/main/java/g0001_0100/s0073_set_matrix_zeroes/readme.md index 7673bb54..d46efebc 100644 --- a/src/main/java/g0001_0100/s0073_set_matrix_zeroes/readme.md +++ b/src/main/java/g0001_0100/s0073_set_matrix_zeroes/readme.md @@ -38,80 +38,55 @@ You must do it [in place](https://en.wikipedia.org/wiki/In-place_algorithm). * A simple improvement uses `O(m + n)` space, but still not the best solution. * Could you devise a constant space solution? -## Solution +To solve the "Set Matrix Zeroes" problem in Java with the Solution class, follow these steps: + +1. Define a method `setZeroes` in the `Solution` class that takes a 2D integer matrix `matrix` as input and modifies it in place to set the entire row and column to zeros if an element is zero. +2. Initialize two boolean arrays `rowZero` and `colZero` of size `m` and `n` respectively, where `m` is the number of rows in the matrix and `n` is the number of columns. These arrays will track whether a row or column needs to be set to zero. +3. Iterate over the matrix to mark the rows and columns that contain zeros: + - If `matrix[i][j]` is zero, set `rowZero[i] = true` and `colZero[j] = true`. +4. Iterate over the matrix again and set the entire row to zeros if `rowZero[i] = true` or the entire column to zeros if `colZero[j] = true`. +5. Return the modified matrix. + +Here's the implementation of the `setZeroes` method in Java: ```java -public class Solution { - // Approach: Use first row and first column for storing whether in future - // the entire row or column needs to be marked 0 +class Solution { public void setZeroes(int[][] matrix) { int m = matrix.length; int n = matrix[0].length; - boolean row0 = false; - boolean col0 = false; - // Check if 0th col needs to be market all 0s in future - for (int[] ints : matrix) { - if (ints[0] == 0) { - col0 = true; - break; - } - } - // Check if 0th row needs to be market all 0s in future - for (int i = 0; i < n; i++) { - if (matrix[0][i] == 0) { - row0 = true; - break; - } - } - // Store the signals in 0th row and column - for (int i = 1; i < m; i++) { - for (int j = 1; j < n; j++) { + + boolean[] rowZero = new boolean[m]; + boolean[] colZero = new boolean[n]; + + // Mark rows and columns containing zeros + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { if (matrix[i][j] == 0) { - matrix[i][0] = 0; - matrix[0][j] = 0; + rowZero[i] = true; + colZero[j] = true; } } } - // Mark 0 for all cells based on signal from 0th row and 0th column - for (int i = 1; i < m; i++) { - for (int j = 1; j < n; j++) { - if (matrix[i][0] == 0 || matrix[0][j] == 0) { + + // Set rows to zero + for (int i = 0; i < m; i++) { + if (rowZero[i]) { + for (int j = 0; j < n; j++) { matrix[i][j] = 0; } } } - // Set 0th column - for (int i = 0; i < m; i++) { - if (col0) { - matrix[i][0] = 0; - } - } - // Set 0th row - for (int i = 0; i < n; i++) { - if (row0) { - matrix[0][i] = 0; + + // Set columns to zero + for (int j = 0; j < n; j++) { + if (colZero[j]) { + for (int i = 0; i < m; i++) { + matrix[i][j] = 0; + } } } } } ``` -**Time Complexity (Big O Time):** - -1. The program first iterates through the matrix to determine whether the first row and first column need to be marked as zero (i.e., `row0` and `col0` flags). - -2. Then, it iterates through the entire matrix twice: - - The first iteration (nested loops) is used to identify cells that need to be marked as zero based on the conditions. This loop runs for `(m-1) * (n-1)` iterations, where `m` is the number of rows, and `n` is the number of columns. - - The second iteration (nested loops) is used to actually set the cells to zero based on the signals stored in the first row and first column. This loop also runs for `(m-1) * (n-1)` iterations. - -3. The program also sets the first row and first column to zero if necessary. - -4. Therefore, the overall time complexity of the program is O(m * n), where `m` is the number of rows, and `n` is the number of columns. - -**Space Complexity (Big O Space):** - -1. The program uses only a few additional boolean variables (`row0` and `col0`) and integer variables (loop counters). These variables consume constant space, which does not depend on the size of the input matrix. - -2. The program modifies the input matrix in-place without using any additional data structures. Therefore, the space complexity of the program is O(1) or constant space. - -In summary, the time complexity of the provided program is O(m * n), and the space complexity is O(1). The program efficiently sets rows and columns of a matrix to zero based on specific conditions while using minimal extra space. +This implementation modifies the matrix in place to set entire rows and columns to zeros, with a time complexity of O(m * n) and a space complexity of O(m + n), where `m` is the number of rows and `n` is the number of columns in the matrix. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0074_search_a_2d_matrix/readme.md b/src/main/java/g0001_0100/s0074_search_a_2d_matrix/readme.md index 8b8dccda..752fda3e 100644 --- a/src/main/java/g0001_0100/s0074_search_a_2d_matrix/readme.md +++ b/src/main/java/g0001_0100/s0074_search_a_2d_matrix/readme.md @@ -33,48 +33,40 @@ Write an efficient algorithm that searches for a value in an `m x n` matrix. Thi * `1 <= m, n <= 100` * -104 <= matrix[i][j], target <= 104 -## Solution +To solve the "Search a 2D Matrix" problem in Java with the Solution class, follow these steps: + +1. Define a method `searchMatrix` in the `Solution` class that takes a 2D integer matrix `matrix` and an integer `target` as input and returns `true` if the target value is found in the matrix, otherwise returns `false`. +2. Initialize two pointers `row` and `col` to start at the top-right corner of the matrix. `row` starts from 0 and `col` starts from the last column. +3. Loop until `row` is less than the number of rows in the matrix and `col` is greater than or equal to 0: + - If `matrix[row][col]` is equal to the target, return `true`. + - If `matrix[row][col]` is greater than the target, decrement `col`. + - If `matrix[row][col]` is less than the target, increment `row`. +4. If the target is not found after the loop, return `false`. + +Here's the implementation of the `searchMatrix` method in Java: ```java -public class Solution { +class Solution { public boolean searchMatrix(int[][] matrix, int target) { - int endRow = matrix.length; - int endCol = matrix[0].length; - int targetRow = 0; - boolean result = false; - for (int i = 0; i < endRow; i++) { - if (matrix[i][endCol - 1] >= target) { - targetRow = i; - break; - } - } - for (int i = 0; i < endCol; i++) { - if (matrix[targetRow][i] == target) { - result = true; - break; + int m = matrix.length; + int n = matrix[0].length; + + int row = 0; + int col = n - 1; + + while (row < m && col >= 0) { + if (matrix[row][col] == target) { + return true; + } else if (matrix[row][col] > target) { + col--; + } else { + row++; } } - return result; + + return false; } } ``` -**Time Complexity (Big O Time):** - -1. The program first determines the number of rows (`endRow`) and columns (`endCol`) in the matrix, which takes O(1) time. - -2. It then iterates through the rows once to find the target row where the last element of each row is greater than or equal to the target. This loop runs in O(endRow) time, where `endRow` is the number of rows in the matrix. - -3. Once the target row is identified, the program iterates through the elements in that row to check if the target exists in that row. This loop runs in O(endCol) time, where `endCol` is the number of columns in the matrix. - -4. Therefore, the overall time complexity of the program is O(endRow + endCol), where `endRow` is the number of rows and `endCol` is the number of columns in the matrix. - -**Space Complexity (Big O Space):** - -1. The program uses a few integer variables (such as `endRow`, `endCol`, and `targetRow`) and a boolean variable (`result`) to store intermediate values. These variables consume constant space, which does not depend on the size of the input matrix. - -2. The program does not use any additional data structures or arrays that scale with the size of the input matrix. - -3. Therefore, the space complexity of the program is O(1) or constant space. - -In summary, the time complexity of the provided program is O(endRow + endCol), and the space complexity is O(1). The program efficiently searches for a target element in a 2D matrix, considering the properties of the matrix, without using additional memory for data structures. +This implementation searches for the target value efficiently in the given matrix by starting from the top-right corner and moving either left or down based on the comparison with the target value. The time complexity of this solution is O(m + n), where m is the number of rows and n is the number of columns in the matrix. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0075_sort_colors/readme.md b/src/main/java/g0001_0100/s0075_sort_colors/readme.md index 0b9ef74f..d2e7ca1a 100644 --- a/src/main/java/g0001_0100/s0075_sort_colors/readme.md +++ b/src/main/java/g0001_0100/s0075_sort_colors/readme.md @@ -43,47 +43,45 @@ You must solve this problem without using the library's sort function. **Follow up:** Could you come up with a one-pass algorithm using only constant extra space? -## Solution +To solve the "Sort Colors" problem in Java with the Solution class, follow these steps: + +1. Define a method `sortColors` in the `Solution` class that takes an array of integers `nums` as input and sorts it in-place according to the colors red, white, and blue. +2. Initialize three pointers: `low`, `mid`, and `high`. `low` points to the beginning of the array, `mid` points to the current element being processed, and `high` points to the end of the array. +3. Loop while `mid` is less than or equal to `high`: + - If `nums[mid]` is 0, swap `nums[low]` with `nums[mid]`, increment `low` and `mid`. + - If `nums[mid]` is 1, increment `mid`. + - If `nums[mid]` is 2, swap `nums[mid]` with `nums[high]`, decrement `high`. +4. After the loop, the array will be sorted in-place according to the colors red, white, and blue. + +Here's the implementation of the `sortColors` method in Java: ```java -public class Solution { +class Solution { public void sortColors(int[] nums) { - int zeroes = 0; - int ones = 0; - for (int i = 0; i < nums.length; i++) { - if (nums[i] == 0) { - nums[zeroes++] = 0; - } else if (nums[i] == 1) { - ones++; + int low = 0; + int mid = 0; + int high = nums.length - 1; + + while (mid <= high) { + if (nums[mid] == 0) { + swap(nums, low, mid); + low++; + mid++; + } else if (nums[mid] == 1) { + mid++; + } else { + swap(nums, mid, high); + high--; } } - for (int j = zeroes; j < zeroes + ones; j++) { - nums[j] = 1; - } - for (int k = zeroes + ones; k < nums.length; k++) { - nums[k] = 2; - } + } + + private void swap(int[] nums, int i, int j) { + int temp = nums[i]; + nums[i] = nums[j]; + nums[j] = temp; } } ``` -**Time Complexity (Big O Time):** - -1. The program iterates through the input array `nums` once to count the number of zeroes and ones. This loop runs in O(n) time, where `n` is the length of the input array. - -2. After counting the zeroes and ones, the program performs two additional loops: - - The first loop fills the first `zeroes` elements of the array with zeroes. This loop runs in O(zeroes) time. - - The second loop fills the next `ones` elements of the array with ones. This loop runs in O(ones) time. - - Finally, the program fills the remaining elements with twos, which can be calculated as `n - zeroes - ones`. This operation also runs in O(n) time. - -3. Therefore, the overall time complexity of the program is O(n) because the dominant factor is the single iteration through the array. - -**Space Complexity (Big O Space):** - -1. The program uses a constant amount of extra space for integer variables (`zeroes`, `ones`) and loop counters. This extra space does not depend on the size of the input array and is considered constant. - -2. The program does not use any additional data structures or arrays that scale with the size of the input array. - -3. Therefore, the space complexity of the program is O(1), or constant space. - -In summary, the time complexity of the provided program is O(n), and the space complexity is O(1). The program efficiently sorts an array of 0s, 1s, and 2s in a single pass without using additional memory for data structures. +This implementation sorts the array in-place using a one-pass algorithm with constant extra space. It iterates through the array and swaps elements as needed to group them according to their colors. The time complexity of this solution is O(n), where n is the length of the array. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0076_minimum_window_substring/readme.md b/src/main/java/g0001_0100/s0076_minimum_window_substring/readme.md index 7a616a56..821a9403 100644 --- a/src/main/java/g0001_0100/s0076_minimum_window_substring/readme.md +++ b/src/main/java/g0001_0100/s0076_minimum_window_substring/readme.md @@ -44,57 +44,73 @@ A **substring** is a contiguous sequence of characters within the string. **Follow up:** Could you find an algorithm that runs in `O(m + n)` time? -## Solution +To solve the "Minimum Window Substring" problem in Java with the Solution class, follow these steps: + +1. Define a method `minWindow` in the `Solution` class that takes two strings `s` and `t` as input and returns the minimum window substring of `s` containing all characters from `t`. +2. Create two frequency maps: `tFreqMap` to store the frequency of characters in string `t`, and `sFreqMap` to store the frequency of characters in the current window of string `s`. +3. Initialize two pointers `left` and `right` to track the window boundaries. Initialize a variable `minLength` to store the minimum window length found so far. +4. Iterate over string `s` using the `right` pointer until the end of the string: + - Update the frequency map `sFreqMap` for the character at index `right`. + - Check if the current window contains all characters from `t`. If it does, move the `left` pointer to minimize the window while maintaining the condition. + - Update the `minLength` if the current window length is smaller. + - Move the `right` pointer to expand the window. +5. Return the minimum window substring found, or an empty string if no such substring exists. + +Here's the implementation of the `minWindow` method in Java: ```java -public class Solution { +import java.util.HashMap; +import java.util.Map; + +class Solution { public String minWindow(String s, String t) { - int[] map = new int[128]; - for (int i = 0; i < t.length(); i++) { - map[t.charAt(i) - 'A']++; + Map tFreqMap = new HashMap<>(); + Map sFreqMap = new HashMap<>(); + + // Initialize tFreqMap with character frequencies from string t + for (char ch : t.toCharArray()) { + tFreqMap.put(ch, tFreqMap.getOrDefault(ch, 0) + 1); } - int count = t.length(); - int begin = 0; - int end = 0; - int d = Integer.MAX_VALUE; - int head = 0; - while (end < s.length()) { - if (map[s.charAt(end++) - 'A']-- > 0) { - count--; - } - while (count == 0) { - if (end - begin < d) { - d = end - begin; - head = begin; - } - if (map[s.charAt(begin++) - 'A']++ == 0) { - count++; + + int left = 0; + int right = 0; + int minLength = Integer.MAX_VALUE; + int minStart = 0; + + while (right < s.length()) { + char rightChar = s.charAt(right); + sFreqMap.put(rightChar, sFreqMap.getOrDefault(rightChar, 0) + 1); + right++; + + // Check if the current window contains all characters from t + while (containsAllChars(sFreqMap, tFreqMap)) { + // Update the minimum window length + if (right - left < minLength) { + minLength = right - left; + minStart = left; } + + char leftChar = s.charAt(left); + sFreqMap.put(leftChar, sFreqMap.get(leftChar) - 1); + left++; } } - return d == Integer.MAX_VALUE ? "" : s.substring(head, head + d); + + return minLength == Integer.MAX_VALUE ? "" : s.substring(minStart, minStart + minLength); + } + + // Helper method to check if sFreqMap contains all characters from tFreqMap + private boolean containsAllChars(Map sFreqMap, Map tFreqMap) { + for (Map.Entry entry : tFreqMap.entrySet()) { + char ch = entry.getKey(); + int count = entry.getValue(); + if (sFreqMap.getOrDefault(ch, 0) < count) { + return false; + } + } + return true; } } ``` -**Time Complexity (Big O Time):** - -1. The program begins by creating an integer array `map` of size 128 to store character frequencies. It iterates through the characters in string `t` once, incrementing the corresponding count in the `map`. This initialization step runs in O(t.length()) time. - -2. The main part of the program uses two pointers, `begin` and `end`, to slide through string `s`. This part contains a while loop that iterates through the entire string `s`. In the worst case, the loop can iterate over each character in `s` twice (once for `end` and once for `begin`), so it runs in O(2 * s.length()) time. - -3. Within the loop, there is a nested while loop that adjusts the `begin` pointer and updates the minimum window. The number of iterations of this inner loop depends on the length of the window and the contents of string `s` and string `t`. In the worst case, this inner loop can iterate through the entire string `s` once. Therefore, the inner loop's time complexity is O(s.length()). - -4. The overall time complexity of the program is dominated by the two iterations over `s`. Therefore, the time complexity is O(s.length()). - -**Space Complexity (Big O Space):** - -1. The program uses additional space for the integer array `map`, which has a fixed size of 128 characters (assuming ASCII characters). This space complexity is constant, O(1), because the size of `map` does not depend on the input strings `s` and `t`. - -2. The program uses several integer variables (`count`, `begin`, `end`, `d`, `head`) to keep track of indices and counts. These variables consume a constant amount of space, which is also O(1). - -3. The program does not use additional data structures or arrays that scale with the size of the input strings. - -4. Therefore, the space complexity of the program is O(1), or constant space. - -In summary, the time complexity of the provided program is O(s.length()), and the space complexity is O(1). The program efficiently finds the minimum window in string `s` containing all characters from string `t`. +This implementation finds the minimum window substring in `O(m + n)` time complexity, where `m` is the length of string `s` and `n` is the length of string `t`. It uses two frequency maps to keep track of character frequencies and adjusts the window boundaries to find the minimum window containing all characters from `t`. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0078_subsets/readme.md b/src/main/java/g0001_0100/s0078_subsets/readme.md index 219445b6..4c60b702 100644 --- a/src/main/java/g0001_0100/s0078_subsets/readme.md +++ b/src/main/java/g0001_0100/s0078_subsets/readme.md @@ -27,51 +27,47 @@ The solution set **must not** contain duplicate subsets. Return the solution in * `-10 <= nums[i] <= 10` * All the numbers of `nums` are **unique**. -## Solution +To solve the "Subsets" problem in Java with the Solution class, follow these steps: + +1. Define a method `subsets` in the `Solution` class that takes an integer array `nums` as input and returns all possible subsets of `nums`. +2. Initialize an empty list to store the result subsets. +3. Implement a backtracking algorithm to generate all possible subsets: + - Define a recursive helper function `generateSubsets` that takes the current subset, the current index in the array, and the array `nums` as parameters. + - Base case: If the current index is equal to the length of `nums`, add the current subset to the result list. + - Recursive case: + - Include the current element in the subset and recursively call `generateSubsets` with the next index. + - Exclude the current element from the subset and recursively call `generateSubsets` with the next index. +4. Call the `generateSubsets` function with an empty subset and the starting index 0. +5. Return the list containing all subsets. + +Here's the implementation of the `subsets` method in Java: ```java import java.util.ArrayList; import java.util.List; -@SuppressWarnings("java:S5413") -public class Solution { +class Solution { public List> subsets(int[] nums) { - List> res = new ArrayList<>(); - solve(nums, new ArrayList<>(), res, 0); - return res; + List> result = new ArrayList<>(); + generateSubsets(new ArrayList<>(), 0, nums, result); + return result; } - - private void solve(int[] nums, List temp, List> res, int start) { - res.add(new ArrayList<>(temp)); - for (int i = start; i < nums.length; i++) { - temp.add(nums[i]); - solve(nums, temp, res, i + 1); - temp.remove(temp.size() - 1); + + private void generateSubsets(List subset, int index, int[] nums, List> result) { + // Base case: add the current subset to the result list + result.add(new ArrayList<>(subset)); + + // Recursive case + for (int i = index; i < nums.length; i++) { + // Include the current element in the subset + subset.add(nums[i]); + // Recursively generate subsets starting from the next index + generateSubsets(subset, i + 1, nums, result); + // Exclude the current element from the subset + subset.remove(subset.size() - 1); } } } ``` -**Time Complexity (Big O Time):** - -1. The program uses a recursive approach to generate subsets. It starts with an empty subset and adds elements from the input array `nums` one by one. - -2. Inside the `solve` function, there's a loop that iterates from `start` to the length of the `nums` array. In each iteration, it adds an element to the `temp` list, calls the `solve` function recursively, and then removes the added element from `temp`. - -3. The recursive `solve` function is called for each element in the `nums` array, and each time it adds the current subset to the result list `res`. Therefore, the function is called 2^n times, where 'n' is the length of the `nums` array, because for each element, there are two choices: either include it in the current subset or exclude it. - -4. Inside the loop, the operations performed (addition, recursion, removal) are constant time operations. - -5. As a result, the overall time complexity of the program is O(2^n), where 'n' is the length of the input array `nums`. This is because it generates all possible subsets of the input array. - -**Space Complexity (Big O Space):** - -1. The space complexity is primarily determined by the space used for the result list `res` and the recursive call stack. - -2. The result list `res` stores all the subsets. In the worst case, when `nums` contains 'n' elements, there can be 2^n subsets (including the empty subset). Each subset is a list of integers containing at most 'n' elements. Therefore, the space complexity for `res` is O(2^n * n), which simplifies to O(n * 2^n). - -3. The space used by the recursive call stack depends on the depth of the recursion, which is at most 'n' (the number of elements in `nums`). For each recursive call, a constant amount of space is used to store the `temp` list. Therefore, the space complexity due to the call stack is O(n). - -4. Combining the space complexities of the result list and the call stack, the overall space complexity is O(n * 2^n). - -In summary, the time complexity of the program is O(2^n), and the space complexity is O(n * 2^n), where 'n' is the length of the input array `nums`. This program efficiently generates all possible subsets of `nums` using a recursive approach. +This implementation uses backtracking to generate all possible subsets of the input array `nums`. It has a time complexity of O(2^N), where N is the number of elements in the input array. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0079_word_search/readme.md b/src/main/java/g0001_0100/s0079_word_search/readme.md index dcef8e4b..2b63bcf5 100644 --- a/src/main/java/g0001_0100/s0079_word_search/readme.md +++ b/src/main/java/g0001_0100/s0079_word_search/readme.md @@ -43,69 +43,53 @@ The word can be constructed from letters of sequentially adjacent cells, where a **Follow up:** Could you use search pruning to make your solution faster with a larger `board`? -## Solution +To solve the "Word Search" problem in Java with the Solution class, follow these steps: + +1. Define a method `exist` in the `Solution` class that takes a 2D character array `board` and a string `word` as input and returns `true` if the `word` exists in the `board`. +2. Implement a backtracking algorithm to search for the `word` in the `board`. +3. Iterate through each cell in the `board`: + - For each cell, call a recursive helper function `search` to check if the `word` can be found starting from that cell. + - If `search` returns `true`, return `true` immediately. +4. Define the `search` method to perform the recursive backtracking: + - Check if the current cell is out of bounds or if the current character in the `board` does not match the corresponding character in the `word`. + - If any of the conditions are met, return `false`. + - Mark the current cell as visited by changing its value to a special character (e.g., `#`) to avoid revisiting it. + - Recursively call `search` on neighboring cells (up, down, left, right) with the next character in the `word`. + - After exploring all possible paths from the current cell, backtrack by restoring the original value of the current cell. +5. If the `search` method reaches the end of the `word`, return `true`. +6. If no match is found after exploring all cells, return `false`. + +Here's the implementation of the `exist` method in Java: ```java -public class Solution { - private boolean backtrace( - char[][] board, boolean[][] visited, String word, int index, int x, int y) { - if (index == word.length()) { - return true; - } - if (x < 0 || x >= board.length || y < 0 || y >= board[0].length || visited[x][y]) { - return false; - } - visited[x][y] = true; - if (word.charAt(index) == board[x][y]) { - boolean res = - backtrace(board, visited, word, index + 1, x, y + 1) - || backtrace(board, visited, word, index + 1, x, y - 1) - || backtrace(board, visited, word, index + 1, x + 1, y) - || backtrace(board, visited, word, index + 1, x - 1, y); - if (!res) { - visited[x][y] = false; - } - return res; - } else { - visited[x][y] = false; - return false; - } - } - +class Solution { public boolean exist(char[][] board, String word) { - boolean[][] visited = new boolean[board.length][board[0].length]; - for (int i = 0; i < board.length; ++i) { - for (int j = 0; j < board[0].length; ++j) { - if (backtrace(board, visited, word, 0, i, j)) { + int m = board.length; + int n = board[0].length; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (search(board, word, i, j, 0)) return true; - } } } return false; } + + private boolean search(char[][] board, String word, int i, int j, int index) { + if (index == word.length()) + return true; + if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != word.charAt(index)) + return false; + char temp = board[i][j]; + board[i][j] = '#'; // Mark as visited + boolean found = search(board, word, i + 1, j, index + 1) || + search(board, word, i - 1, j, index + 1) || + search(board, word, i, j + 1, index + 1) || + search(board, word, i, j - 1, index + 1); + board[i][j] = temp; // Restore original value + return found; + } } ``` -**Time Complexity (Big O Time):** - -1. The program uses a backtracking approach to explore all possible paths in the 2D board while searching for the target word. - -2. The `exist` function iterates over all cells in the board, and for each cell, it invokes the `backtrace` function to start the backtracking process. - -3. The `backtrace` function explores all four possible directions (up, down, left, right) from the current cell. - -4. In the worst case, the `backtrace` function explores all possible paths in the board until it either finds the target word or determines that it cannot be formed. - -5. The time complexity depends on the number of cells in the board (m * n), where 'm' is the number of rows, and 'n' is the number of columns. For each cell, the `backtrace` function explores four possible directions. Therefore, the overall time complexity is O(4^(m*n)), where 'm' and 'n' are the dimensions of the board. - -**Space Complexity (Big O Space):** - -1. The primary space usage in the program comes from the recursive call stack and the `visited` array. - -2. The recursive call stack's maximum depth depends on the number of cells explored during backtracking. In the worst case, where the entire board is explored, the depth can be as large as 'm * n'. Therefore, the space complexity due to the call stack is O(m * n). - -3. The `visited` array is used to keep track of visited cells to avoid revisiting them during the backtracking process. Its size is equal to the number of cells in the board, which is 'm * n'. Therefore, the space complexity due to the `visited` array is also O(m * n). - -4. Combining the space complexities of the call stack and the `visited` array, the overall space complexity is O(m * n). - -In summary, the time complexity of the program is O(4^(m*n)), and the space complexity is O(m * n), where 'm' and 'n' are the dimensions of the board. This program efficiently explores all possible paths in the board to search for the target word using a backtracking approach. +This implementation uses backtracking to search for the word in the board, with a time complexity of O(M * N * 4^L), where M and N are the dimensions of the board and L is the length of the word. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0084_largest_rectangle_in_histogram/readme.md b/src/main/java/g0001_0100/s0084_largest_rectangle_in_histogram/readme.md index d5a4e500..4637c098 100644 --- a/src/main/java/g0001_0100/s0084_largest_rectangle_in_histogram/readme.md +++ b/src/main/java/g0001_0100/s0084_largest_rectangle_in_histogram/readme.md @@ -30,95 +30,46 @@ Given an array of integers `heights` representing the histogram's bar height whe * 1 <= heights.length <= 105 * 0 <= heights[i] <= 104 -## Solution +To solve the "Largest Rectangle in Histogram" problem in Java with the Solution class, follow these steps: -```java -public class Solution { - public int largestRectangleArea(int[] heights) { - return largestArea(heights, 0, heights.length); - } +1. Define a method `largestRectangleArea` in the `Solution` class that takes an array of integers `heights` as input and returns the area of the largest rectangle in the histogram. +2. Implement a stack-based algorithm to find the largest rectangle: + - Initialize a stack to store indices of bars in the histogram. + - Iterate through each bar in the histogram: + - If the stack is empty or the current bar's height is greater than or equal to the height of the bar at the top of the stack, push the current bar's index onto the stack. + - If the current bar's height is less than the height of the bar at the top of the stack, keep popping bars from the stack until either the stack is empty or the height of the bar at the top of the stack is less than the height of the current bar. + - Calculate the area of the rectangle formed by the popped bar using its height and width (the difference between the current index and the index of the previous bar in the stack or -1 if the stack is empty). + - Update the maximum area if the calculated area is greater. + - After iterating through all bars, pop the remaining bars from the stack and calculate the area of rectangles formed by them using the same method as above. +3. Return the maximum area calculated. - private int largestArea(int[] a, int start, int limit) { - if (a == null || a.length == 0) { - return 0; - } - if (start == limit) { - return 0; - } - if (limit - start == 1) { - return a[start]; - } - if (limit - start == 2) { - int maxOfTwoBars = Math.max(a[start], a[start + 1]); - int areaFromTwo = Math.min(a[start], a[start + 1]) * 2; - return Math.max(maxOfTwoBars, areaFromTwo); - } - if (checkIfSorted(a, start, limit)) { - int maxWhenSorted = 0; - for (int i = start; i < limit; i++) { - if (a[i] * (limit - i) > maxWhenSorted) { - maxWhenSorted = a[i] * (limit - i); - } - } - return maxWhenSorted; - } else { - int minInd = findMinInArray(a, start, limit); - return maxOfThreeNums( - largestArea(a, start, minInd), - a[minInd] * (limit - start), - largestArea(a, minInd + 1, limit)); - } - } +Here's the implementation of the `largestRectangleArea` method in Java: - private int findMinInArray(int[] a, int start, int limit) { - int min = Integer.MAX_VALUE; - int minIndex = -1; - for (int index = start; index < limit; index++) { - if (a[index] < min) { - min = a[index]; - minIndex = index; - } - } - return minIndex; - } +```java +import java.util.Stack; - private boolean checkIfSorted(int[] a, int start, int limit) { - for (int i = start + 1; i < limit; i++) { - if (a[i] < a[i - 1]) { - return false; +class Solution { + public int largestRectangleArea(int[] heights) { + Stack stack = new Stack<>(); + int maxArea = 0; + int i = 0; + while (i < heights.length) { + if (stack.isEmpty() || heights[i] >= heights[stack.peek()]) { + stack.push(i++); + } else { + int top = stack.pop(); + int width = stack.isEmpty() ? i : i - stack.peek() - 1; + maxArea = Math.max(maxArea, heights[top] * width); } } - return true; - } - - private int maxOfThreeNums(int a, int b, int c) { - return Math.max(Math.max(a, b), c); + while (!stack.isEmpty()) { + int top = stack.pop(); + int width = stack.isEmpty() ? i : i - stack.peek() - 1; + maxArea = Math.max(maxArea, heights[top] * width); + } + return maxArea; } } ``` -**Time Complexity (Big O Time):** - -The program uses a divide-and-conquer approach to calculate the largest rectangle area. Here's the analysis of the time complexity: - -1. The `largestRectangleArea` function is called initially with the entire array of heights, so the initial function call has a time complexity of O(n), where 'n' is the length of the `heights` array. - -2. The `largestArea` function is called recursively to calculate the largest rectangle area. In each recursive call, it divides the problem into smaller subproblems. The subproblem is divided into two parts or processed linearly based on whether the array is sorted. - -3. In the worst case, the `largestArea` function may make recursive calls on both the left and right halves of the input array, effectively dividing it in half each time. This results in a recursive call tree with a height of log₂(n). - -4. Within each recursive call, there are loops and conditional checks. The loop that finds the minimum value in a subarray has a time complexity of O(n), where 'n' is the size of the subarray. In the worst case, this loop can run for each level of recursion. - -5. Overall, the time complexity can be represented as O(n log n) in the worst case. This is because at each level of recursion, you perform a linear scan of the array, and there are log₂(n) levels of recursion. - -**Space Complexity (Big O Space):** - -The space complexity of the program is primarily determined by the call stack due to recursion and some additional variables. Here's the analysis of space complexity: - -1. The primary space usage is due to the recursive call stack. In the worst case, the maximum depth of the call stack can be log₂(n), where 'n' is the length of the `heights` array. Therefore, the space complexity due to the call stack is O(log n). - -2. The program uses a few additional variables for loop indices and temporary values, but their space usage is constant and does not depend on the size of the input. Therefore, their contribution to space complexity is negligible. - -3. Overall, the dominant factor in space complexity is the recursive call stack, so the space complexity is O(log n) in the worst case. - -In summary, the time complexity of the program is O(n log n) in the worst case, and the space complexity is O(log n) due to the recursive call stack. +This implementation uses a stack-based approach to find the largest rectangle in the histogram, with a time complexity of O(N), where N is the number of bars in the histogram. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0094_binary_tree_inorder_traversal/readme.md b/src/main/java/g0001_0100/s0094_binary_tree_inorder_traversal/readme.md index 79f131be..1456d3e1 100644 --- a/src/main/java/g0001_0100/s0094_binary_tree_inorder_traversal/readme.md +++ b/src/main/java/g0001_0100/s0094_binary_tree_inorder_traversal/readme.md @@ -50,72 +50,44 @@ Given the `root` of a binary tree, return _the inorder traversal of its nodes' v **Follow up:** Recursive solution is trivial, could you do it iteratively? -## Solution +To solve the "Binary Tree Inorder Traversal" problem in Java with the Solution class, follow these steps: + +1. Define a method `inorderTraversal` in the `Solution` class that takes the root of a binary tree as input and returns the inorder traversal of its nodes' values. +2. Implement an iterative algorithm to perform inorder traversal: + - Initialize an empty list to store the inorder traversal result. + - Initialize a stack to track the nodes during traversal. + - Start with the root node and push it onto the stack. + - While the stack is not empty: + - Traverse down the left subtree by pushing all left child nodes onto the stack. + - Pop the top node from the stack and add its value to the traversal result list. + - Move to the right subtree of the popped node and repeat the process. + - Return the traversal result list. +3. Return the inorder traversal result list. + +Here's the implementation of the `inorderTraversal` method in Java: ```java -import com_github_leetcode.TreeNode; import java.util.ArrayList; -import java.util.Collections; import java.util.List; +import java.util.Stack; -/* - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode() {} - * TreeNode(int val) { this.val = val; } - * TreeNode(int val, TreeNode left, TreeNode right) { - * this.val = val; - * this.left = left; - * this.right = right; - * } - * } - */ -public class Solution { +class Solution { public List inorderTraversal(TreeNode root) { - if (root == null) { - return Collections.emptyList(); - } - List answer = new ArrayList<>(); - inorderTraversal(root, answer); - return answer; - } - - public void inorderTraversal(TreeNode root, List answer) { - if (root == null) { - return; - } - if (root.left != null) { - inorderTraversal(root.left, answer); - } - answer.add(root.val); - if (root.right != null) { - inorderTraversal(root.right, answer); + List inorder = new ArrayList<>(); + Stack stack = new Stack<>(); + TreeNode curr = root; + while (curr != null || !stack.isEmpty()) { + while (curr != null) { + stack.push(curr); + curr = curr.left; + } + curr = stack.pop(); + inorder.add(curr.val); + curr = curr.right; } + return inorder; } } ``` -**Time Complexity (Big O Time):** - -The time complexity of the program depends on how many nodes are present in the binary tree. - -- In the worst case, if the binary tree is completely unbalanced (i.e., a skewed tree), the `inorderTraversal` function may have to traverse through all the nodes one by one, resulting in a time complexity of O(n), where 'n' is the number of nodes in the tree. - -- In the best case, if the binary tree is perfectly balanced (i.e., a full binary tree), the `inorderTraversal` function will still visit all 'n' nodes, resulting in a time complexity of O(n). - -- The time complexity is primarily determined by the number of nodes in the tree, so it is O(n) in both the worst and best cases. - -**Space Complexity (Big O Space):** - -The space complexity of the program is determined by the space required for the call stack due to recursive function calls and the space used for the output list. - -- Recursive Call Stack: The `inorderTraversal` function is implemented recursively. In the worst case, where the tree is completely unbalanced, the maximum depth of the call stack will be 'n' (the number of nodes in the tree), as the function makes recursive calls for each node in the tree. Therefore, the space complexity due to the call stack is O(n). - -- Output List: The `answer` list stores the elements of the binary tree in inorder traversal order. It will contain 'n' elements (equal to the number of nodes in the tree), so the space complexity for the output list is O(n). - -- Overall, the space complexity is dominated by the call stack and the output list, so it is O(n) in both the worst and best cases. - -In summary, the time complexity of the program is O(n), and the space complexity is O(n), where 'n' is the number of nodes in the binary tree. +This implementation performs an iterative inorder traversal of the binary tree using a stack, with a time complexity of O(N), where N is the number of nodes in the tree. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0096_unique_binary_search_trees/readme.md b/src/main/java/g0001_0100/s0096_unique_binary_search_trees/readme.md index 0f491cbd..e36cd32d 100644 --- a/src/main/java/g0001_0100/s0096_unique_binary_search_trees/readme.md +++ b/src/main/java/g0001_0100/s0096_unique_binary_search_trees/readme.md @@ -25,38 +25,32 @@ Given an integer `n`, return _the number of structurally unique **BST'**s (binar * `1 <= n <= 19` -## Solution +To solve the "Unique Binary Search Trees" problem in Java with the Solution class, follow these steps: + +1. Define a method `numTrees` in the `Solution` class that takes an integer `n` as input and returns the number of structurally unique BSTs (binary search trees) with exactly `n` nodes. +2. Implement a dynamic programming approach to solve the problem: + - Create an array `dp` of size `n + 1` to store the number of unique BSTs for each number of nodes from 0 to `n`. + - Initialize `dp[0] = 1` and `dp[1] = 1`, as there is only one unique BST for 0 and 1 node(s). + - Use a nested loop to calculate `dp[i]` for each `i` from 2 to `n`. + - For each `i`, calculate `dp[i]` by summing up the products of `dp[j]` and `dp[i - j - 1]` for all possible values of `j` from 0 to `i - 1`. + - Return `dp[n]`, which represents the number of unique BSTs with `n` nodes. + +Here's the implementation of the `numTrees` method in Java: ```java -public class Solution { +class Solution { public int numTrees(int n) { - long result = 1; - for (int i = 0; i < n; i++) { - result *= 2L * n - i; - result /= i + 1; + int[] dp = new int[n + 1]; + dp[0] = 1; + dp[1] = 1; + for (int i = 2; i <= n; i++) { + for (int j = 0; j < i; j++) { + dp[i] += dp[j] * dp[i - j - 1]; + } } - result /= n + 1; - return (int) result; + return dp[n]; } } ``` -**Time Complexity (Big O Time):** - -The program uses a loop that iterates from 0 to 'n' to calculate the number of unique binary search trees. Inside the loop, basic arithmetic operations (multiplication and division) are performed. - -- The loop runs 'n' times, so the time complexity of the loop itself is O(n). - -- Inside the loop, there are simple arithmetic operations involving long integers (multiplication and division), which are constant-time operations. - -- Therefore, the overall time complexity of the program is O(n), where 'n' is the input value. - -**Space Complexity (Big O Space):** - -The program uses a single long variable (`result`) to store the intermediate and final results. It does not use any data structures that depend on the input size 'n'. - -- Regardless of the input value 'n', the space used by the program remains constant. - -- Therefore, the space complexity of the program is O(1), indicating constant space usage. - -In summary, the time complexity of the program is O(n), and the space complexity is O(1), where 'n' is the input value. The time complexity is determined by the loop that runs 'n' times, and the space complexity is constant because the program uses only a fixed amount of memory regardless of the input size. +This implementation uses dynamic programming to compute the number of structurally unique BSTs with `n` nodes in O(n^2) time complexity. \ No newline at end of file diff --git a/src/main/java/g0001_0100/s0098_validate_binary_search_tree/readme.md b/src/main/java/g0001_0100/s0098_validate_binary_search_tree/readme.md index 8bf38a11..3098ebb7 100644 --- a/src/main/java/g0001_0100/s0098_validate_binary_search_tree/readme.md +++ b/src/main/java/g0001_0100/s0098_validate_binary_search_tree/readme.md @@ -36,65 +36,39 @@ A **valid BST** is defined as follows: * The number of nodes in the tree is in the range [1, 104]. * -231 <= Node.val <= 231 - 1 -## Solution +To solve the "Validate Binary Search Tree" problem in Java with the Solution class, follow these steps: + +1. Define a method `isValidBST` in the `Solution` class that takes the root of a binary tree as input and returns true if the tree is a valid binary search tree (BST), and false otherwise. +2. Implement a recursive approach to validate if the given binary tree is a valid BST: + - Define a helper method `isValidBSTHelper` that takes the root node, a lower bound, and an upper bound as input parameters. + - In the `isValidBSTHelper` method, recursively traverse the binary tree nodes. + - At each node, check if its value is within the specified bounds (lower bound and upper bound) for a valid BST. + - If the node's value violates the BST property, return false. + - Otherwise, recursively validate the left and right subtrees by updating the bounds accordingly. + - If both the left and right subtrees are valid BSTs, return true. +3. Call the `isValidBSTHelper` method with the root node and appropriate initial bounds to start the validation process. + +Here's the implementation of the `isValidBST` method in Java: ```java -import com_github_leetcode.TreeNode; - -/* - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode() {} - * TreeNode(int val) { this.val = val; } - * TreeNode(int val, TreeNode left, TreeNode right) { - * this.val = val; - * this.left = left; - * this.right = right; - * } - * } - */ -public class Solution { +class Solution { public boolean isValidBST(TreeNode root) { - return solve(root, Long.MIN_VALUE, Long.MAX_VALUE); + return isValidBSTHelper(root, null, null); } - - // we will send a valid range and check whether the root lies in the range - // and update the range for the subtrees - private boolean solve(TreeNode root, long left, long right) { - if (root == null) { + + private boolean isValidBSTHelper(TreeNode node, Integer lower, Integer upper) { + if (node == null) { return true; } - if (root.val <= left || root.val >= right) { + + int val = node.val; + if ((lower != null && val <= lower) || (upper != null && val >= upper)) { return false; } - return solve(root.left, left, root.val) && solve(root.right, root.val, right); + + return isValidBSTHelper(node.left, lower, val) && isValidBSTHelper(node.right, val, upper); } } ``` -**Time Complexity (Big O Time):** - -The program uses a recursive approach to traverse the binary tree. In each recursive call, it checks whether the current node's value falls within a specified range (represented by `left` and `right`). Here's the analysis of time complexity: - -- In the worst case, the program visits each node once. This happens when the tree is a valid BST, and the program checks every node. - -- Therefore, the time complexity of this program is O(N), where N is the number of nodes in the binary tree. - -**Space Complexity (Big O Space):** - -The space complexity of the program is determined by the space required for the recursive call stack and the space needed for the function arguments and variables. Here's the analysis of space complexity: - -- The main function `isValidBST` has a constant amount of space overhead. It doesn't use any additional data structures or arrays that depend on the input size. - -- The recursive function `solve` is called recursively for each node in the binary tree. In the worst case, when the binary tree is a valid BST, the maximum depth of the call stack is equal to the height of the tree. In a balanced BST, this height is log(N), where N is the number of nodes. - -- Therefore, the space complexity due to the call stack is O(log(N)) in the best-case scenario (balanced tree) and O(N) in the worst-case scenario (skewed tree). - -- The space used for function arguments and variables (e.g., `left`, `right`, and `root`) is constant and does not depend on the input size. - -- Overall, the space complexity of the program is O(log(N)) in the best-case scenario and O(N) in the worst-case scenario. - -In summary, the time complexity of the program is O(N), where N is the number of nodes in the binary tree, and the space complexity is O(log(N)) in the best-case scenario and O(N) in the worst-case scenario. The space complexity is mainly determined by the depth of the call stack when checking a skewed tree. +This implementation recursively validates whether the given binary tree is a valid BST in O(n) time complexity, where n is the number of nodes in the tree. \ No newline at end of file diff --git a/src/main/java/g0101_0200/s0101_symmetric_tree/readme.md b/src/main/java/g0101_0200/s0101_symmetric_tree/readme.md index 6e079077..e9d7ffa6 100644 --- a/src/main/java/g0101_0200/s0101_symmetric_tree/readme.md +++ b/src/main/java/g0101_0200/s0101_symmetric_tree/readme.md @@ -30,66 +30,37 @@ Given the `root` of a binary tree, _check whether it is a mirror of itself_ (i.e **Follow up:** Could you solve it both recursively and iteratively? -## Solution +To solve the "Symmetric Tree" problem in Java with the Solution class, follow these steps: + +1. Define a method `isSymmetric` in the `Solution` class that takes the root of a binary tree as input and returns true if the tree is symmetric, and false otherwise. +2. Implement a recursive approach to check if the given binary tree is symmetric: + - Define a helper method `isMirror` that takes two tree nodes as input parameters. + - In the `isMirror` method, recursively compare the left and right subtrees of the given nodes. + - At each step, check if the values of the corresponding nodes are equal and if the left subtree of one node is a mirror image of the right subtree of the other node. + - If both conditions are satisfied for all corresponding nodes, return true; otherwise, return false. +3. Call the `isMirror` method with the root's left and right children to check if the entire tree is symmetric. + +Here's the implementation of the `isSymmetric` method in Java: ```java -import com_github_leetcode.TreeNode; - -/* - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode() {} - * TreeNode(int val) { this.val = val; } - * TreeNode(int val, TreeNode left, TreeNode right) { - * this.val = val; - * this.left = left; - * this.right = right; - * } - * } - */ -public class Solution { +class Solution { public boolean isSymmetric(TreeNode root) { if (root == null) { return true; } - return helper(root.left, root.right); + return isMirror(root.left, root.right); } - - private boolean helper(TreeNode leftNode, TreeNode rightNode) { - if (leftNode == null || rightNode == null) { - return leftNode == null && rightNode == null; + + private boolean isMirror(TreeNode left, TreeNode right) { + if (left == null && right == null) { + return true; } - if (leftNode.val != rightNode.val) { + if (left == null || right == null) { return false; } - return helper(leftNode.left, rightNode.right) && helper(leftNode.right, rightNode.left); + return (left.val == right.val) && isMirror(left.left, right.right) && isMirror(left.right, right.left); } } ``` -**Time Complexity (Big O Time):** - -The program uses a recursive approach to check if the binary tree is symmetric. It recursively compares the left subtree of the root with the right subtree of the root. Here's the analysis of time complexity: - -- In the worst case, the program visits each node once. This happens when the tree is perfectly symmetric (a mirror image of itself), and the program checks every node. - -- Therefore, the time complexity of this program is O(N), where N is the number of nodes in the binary tree. - -**Space Complexity (Big O Space):** - -The space complexity of the program is determined by the space required for the recursive call stack and the space needed for the function arguments and variables. Here's the analysis of space complexity: - -- The main function `isSymmetric` has a constant amount of space overhead. It doesn't use any additional data structures or arrays that depend on the input size. - -- The recursive function `helper` is called recursively for each pair of nodes in the tree. In the worst case, when the binary tree is perfectly symmetric, the maximum depth of the call stack is equal to the height of the tree. In a balanced tree, this height is log(N), where N is the number of nodes. - -- Therefore, the space complexity due to the call stack is O(log(N)) in the best-case scenario (balanced tree) and O(N) in the worst-case scenario (skewed tree). - -- The space used for function arguments and variables (e.g., `leftNode`, `rightNode`) is constant and does not depend on the input size. - -- Overall, the space complexity of the program is O(log(N)) in the best-case scenario and O(N) in the worst-case scenario. The space complexity is mainly determined by the depth of the call stack when checking a perfectly symmetric tree. - -In summary, the time complexity of the program is O(N), where N is the number of nodes in the binary tree, and the space complexity is O(log(N)) in the best-case scenario (perfectly symmetric tree) and O(N) in the worst-case scenario (skewed tree). The space complexity is primarily determined by the depth of the call stack when checking a symmetric tree. +This implementation recursively checks whether the given binary tree is symmetric around its center in O(n) time complexity, where n is the number of nodes in the tree. \ No newline at end of file