Move all solutions into separate directory (cleanup)

the beginning
This commit is contained in:
2023-10-06 03:14:09 -05:00
parent 5ed552fb17
commit 9e0c58faff
26 changed files with 9 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
// Accepted
// Runtime: 1 ms
// Memory Usage: 39.3 MB
// Submitted: January 15th, 2021
/**
* 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; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode a, ListNode b) {
ListNode dummy = new ListNode(0);
ListNode cur = dummy;
int carry = 0;
while (a != null || b != null) {
int x = (a != null) ? a.val : 0;
int y = (b != null) ? b.val : 0;
int sum = carry + x + y;
carry = sum / 10;
cur.next = new ListNode(sum % 10);
cur = cur.next;
if (a != null) a = a.next;
if (b != null) b = b.next;
}
if (carry > 0)
cur.next = new ListNode(carry);
return dummy.next;
}
}

View File

@@ -0,0 +1,9 @@
{
"name": "Add Two Numbers",
"solutions": [
{
"name": "Java",
"path": "Solution.java"
}
]
}

View File

@@ -0,0 +1,22 @@
// Accepted
// Runtime: 7 ms
// Memory Usage: 39.6 MB
// Submitted: January 14th, 2021
class Solution {
public int firstUniqChar(String s) {
int[] count = new int[26]; //
int n = s.length();
// Count the appearances of each character
for (int i = 0; i < n; i++)
count[s.charAt(i) - 'a']++;
// Iterate only the array again, return the index of the character that only appeared once
for (int i = 0; i < n; i++)
if (count[s.charAt(i) - 'a'] == 1)
return i;
return -1;
}
}

View File

@@ -0,0 +1,24 @@
// Accepted
// Runtime: 23 ms
// Memory Usage: 39.5 MB
// Submitted: January 14th, 2021
class Solution {
public int firstUniqChar(String s) {
Map<Character, Integer> count = new HashMap<Character, Integer>();
// Count the number of appearances of each character
for (int i = 0; i < s.length(); i++) {
char val = s.charAt(i);
count.put(val, count.getOrDefault(val, 0) + 1);
}
// Iterate along the array again, and find the first character that only appears once
for (int i = 0; i < s.length(); i++) {
if (count.get(s.charAt(i)) == 1)
return i;
}
return -1;
}
}

View File

@@ -0,0 +1,39 @@
// Accepted
// Runtime: 24 ms
// Memory Usage: 39.3 MB
// Submitted: January 13th, 2021
class Solution {
public String longestPalindrome(String s) {
int left = 0;
int right = 0;
int curMax = 0;
for (int i = 0; i < s.length(); i++) {
// Check both single and double char palindrome
int len = Math.max(expandAround(s, i, i), expandAround(s, i, i + 1));
// If palindrome substring found is larger, switch out (calculate new value range)
if (len > curMax) {
left = i - (len - 1) / 2;
right = i + len / 2;
curMax = len;
}
}
return s.substring(left, right + 1);
}
// Finds the largest palindrome at a specific area
public int expandAround(String s, int left, int right) {
// Ensure it doesn't expand outside boundaries
// Check that left and right character equal eachother
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
// Expand!
left--;
right++;
}
return right - left - 1;
}
}

View File

@@ -0,0 +1,38 @@
// Accepted
// Runtime: 30 ms
// Memory Usage: 39.1 MB
// Submitted: January 14th, 2021
class Solution {
public int longestStrChain(String[] words) {
Map<String, Integer> chain = new HashMap<String, Integer>();
int longest = 0;
Arrays.sort(words, (a, b) -> a.length() - b.length());
// Iterate from shortest to longest words, as previously sorted
for (String word : words) {
chain.put(word, 1); // 1 length chain default
// Skip immediately, no 0 length words will ever be in input
if (word.length() == 1)
continue;
else {
for (int i = 0; i < word.length(); i++) {
// Remove a char at once instance, and render the possible previous chain string
StringBuilder sb = new StringBuilder(word);
String test = sb.deleteCharAt(i).toString();
// Check if the new chain we've found is larger than the last chain
if (chain.containsKey(test) && chain.get(test) + 1 > chain.get(word))
chain.put(word, chain.get(test) + 1);
}
}
// Update answer if we've found a new longest chain
longest = Math.max(longest, chain.get(word));
}
return longest;
}
}

View File

@@ -0,0 +1,26 @@
// Accepted
// Runtime: 4 ms
// Memory Usage: 39.1 MB
// Submitted: January 13th, 2021
class Solution {
public int lengthOfLongestSubstring(String s) {
int max = 0;
// Map stores the character's (latest_index + 1)
Map<Character, Integer> map = new HashMap<Character, Integer>();
int i = 0;
for (int j = 0; j < s.length(); j++) {
char c = s.charAt(j);
// If we've already seen this character, move up i (if needed)
if (map.containsKey(c))
i = Math.max(map.get(c), i);
max = Math.max(max, j - i + 1);
map.put(c, j + 1);
}
return max;
}
}

View File

@@ -0,0 +1,35 @@
// Accepted
// Runtime: 41 ms
// Memory Usage: 54.7 MB
// Submitted: January 14th, 2021
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Solution {
HashMap<String, Integer> count = new HashMap<String, Integer>();
public String[] getFolderNames(String[] names) {
String[] results = new String[names.length];
for (int i = 0; i < names.length; i++) {
if (count.containsKey(names[i])) {
int k = count.get(names[i]) + 1;
String test;
do {
test = names[i] + "(" + k++ + ")";
} while (count.containsKey(test));
count.put(test, 0);
count.put(names[i], k - 1);
results[i] = test;
} else {
count.put(names[i], 0);
results[i] = names[i];
}
}
return results;
}
}

View File

@@ -0,0 +1,18 @@
# Accepted
# Runtime: 7932 ms
# Memory Usage: 26.5 MB
# Submitted: January 14th, 2021
class Solution:
def getFolderNames(self, names: List[str]) -> List[str]:
result = []
names_used = set()
for name in names:
counter = 0
test_name = name
while test_name in names_used:
counter += 1
test_name = f'{name}({counter})'
names_used.add(test_name)
result.append(test_name)
return result

View File

@@ -0,0 +1,90 @@
// Accepted
// Runtime: 549 ms
// Memory Usage: 52.8 MB
// Submitted: January 14th, 2021
// Notes: This solution was pretty bad. I didn't understand how the problem could be solved and made a needlessly more complex and specific solution
// that worked, but it also used RegEx, did operations it didn't need to, and overall was much too complex and aggressive to work well.
// The correct solution was much simpler and more concise. It did technically work, though!
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Solution {
public String[] getFolderNames(String[] names) {
Map<String, Set<Integer>> nameCount = new HashMap<String, Set<Integer>>();
List<String> submit = new ArrayList<String>(names.length);
Pattern p = Pattern.compile("(.+)\\((\\d+)\\)");
for (int i = 0; i < names.length; i++) {
String name = names[i];
Matcher m = p.matcher(name);
// The filename provided has a k-value suffix
if (m.matches()) {
String strippedName = m.group(1);
int k = Integer.parseInt(m.group(2));
// If the stripped name has already been seen
if (nameCount.containsKey(strippedName)) {
// If the k-value has already been recorded
if (nameCount.get(strippedName).contains(k)) {
// Name has been seen before
if (nameCount.containsKey(name)) {
// Get best K value, put new K value in, submit and construct new name
k = GetKValue(nameCount.get(name));
if (k == -1) {
nameCount.get(name).add(-1);
k = GetKValue(nameCount.get(name));
}
nameCount.get(name).add(k);
submit.add(name + "(" + k + ")");
} else {
nameCount.put(name, new HashSet<Integer>());
// We add -1 and skip to 1 immediately as this is a sort of special entry
nameCount.get(name).add(-1);
nameCount.get(name).add(1);
submit.add(name + "(1)");
}
} else {
// It hasn't been recorded before
nameCount.get(strippedName).add(k);
submit.add(name);
}
} else {
// Stripped name has never been seen before
nameCount.put(strippedName, new HashSet<Integer>());
nameCount.get(strippedName).add(k);
submit.add(name);
}
} else {
// Name has been seen before
if (nameCount.containsKey(name)) {
// Get best K value, put new K value in, submit and construct new name
int k = GetKValue(nameCount.get(name));
nameCount.get(name).add(k);
if (k == -1) {
submit.add(name);
} else {
submit.add(name + "(" + k + ")");
}
} else {
nameCount.put(name, new HashSet<Integer>());
nameCount.get(name).add(-1);
submit.add(name);
}
}
}
return submit.toArray(new String[0]);
}
public int GetKValue(Set<Integer> used) {
if (!used.contains(-1))
return -1;
for (int i = 1;; i++) {
if (!used.contains(i))
return i;
}
}
}

View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "median-of-two-sorted-arrays"
version = "0.1.0"

View File

@@ -0,0 +1,8 @@
[package]
name = "median-of-two-sorted-arrays"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@@ -0,0 +1,31 @@
# median-of-two-sorted-arrays
## Two Pointers
When building a merge sort algorithm, the last step is to merge two sorted arrays - just like with this problem (at least for the brute force soluton).
One interesting thing about this is that we can keep track of how far into the final sorted array we are during this 'merge' step.
For example, merging `[1, 2, 3]` and `[2, 7, 9]`, we can determine which index of the final array we are at.
```
[1] => 1
[1, 2] => 2
[1, 2, 2] => 3
[1, 2, 2, 3] => 4
[1, 2, 2, 3, 7] => 5
[1, 2, 2, 3, 7, 9] => 6
```
Given this, we can also determine at what point we have 'reached' the middle of the final array.
Given this, we can extract the middle value(s) from the final array, iterating just like we do during a merge sort, but only until we reach the middle.
In the example above, we reeach the middle at index 3 - and given half the final array's sie is 3 - that's the index we want to stop at.
The actual implementation is with two pointers - the index we're currently iterating over in each array.
We keep track of the last two values we've seen, and when we reach the middle, we can determine if we need to return one or two values.
> For a real implementation, you could setup two different algorithms, one for even-size final arrays, and one for odd. This would remove a couple instructions fo the loop, but given that the Big O is the same - it's not worth it for Leetcode.
## Binary Search
TODO: Writeup

View File

@@ -0,0 +1,44 @@
struct Solution {}
impl Solution {
pub fn find_median_sorted_arrays(a: Vec<i32>, b: Vec<i32>) -> f64 {
let (a_length, b_length) = (a.len(), b.len());
let (mut a_pointer, mut b_pointer, mut current, mut previous) = (0, 0, 0, 0);
for _ in 0..=((a_length+b_length)/2) {
previous = current;
if a_pointer != a_length && b_pointer != b_length {
// Main merge point (as long as both arrays have space to iterate left)
if a[a_pointer] > b[b_pointer] {
current = b[b_pointer];
b_pointer += 1;
} else {
current = a[a_pointer];
a_pointer += 1;
}
} else if a_pointer < a_length {
// Other array has no more space to iterate
current = a[a_pointer];
a_pointer += 1;
} else {
// Other array has no more space to iterate
current = b[b_pointer];
b_pointer += 1;
}
}
if (a_length + b_length) % 2 == 1 {
current as f64
} else {
(current + previous) as f64 / 2.0
}
}
}
fn main() {
println!(
"{}",
Solution::find_median_sorted_arrays(vec![1, 3], vec![2])
);
}

View File

@@ -0,0 +1,27 @@
// Accepted
// Runtime: 7ms
// Memory Usage: 38.5 MB
// Submitted: January 15th, 2021
class Solution {
public boolean isPalindrome(int x) {
if (x < 0)
return false;
else if (x >= 0 && x <= 9)
return true;
byte[] digits = new byte[((int) Math.log10(x)) + 1];
for (int i = 0; i < digits.length; i++) {
digits[i] = (byte) (x % 10);
x /= 10;
}
int n = digits.length / 2;
for (int i = 0; i < n; i++) {
if (digits[i] != digits[digits.length - i - 1])
return false;
}
return true;
}
}

View File

@@ -0,0 +1,20 @@
# Created by https://www.toptal.com/developers/gitignore/api/rust
# Edit at https://www.toptal.com/developers/gitignore?templates=rust
### Rust ###
# Generated by Cargo
# will have compiled files and executables
debug/
target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
# End of https://www.toptal.com/developers/gitignore/api/rust

View File

@@ -0,0 +1,8 @@
[package]
name = "product-of-array-except-self"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@@ -0,0 +1,33 @@
struct Solution {}
impl Solution {
pub fn product_except_self(nums: Vec<i32>) -> Vec<i32> {
let mut result = vec![1; nums.len()];
let mut left = 1;
let mut right = 1;
for i in 0..nums.len() {
// Moving left to right: multiple each number by the preceding number
result[i] *= left;
left *= nums[i];
// Moving right to left, multiple each number by the following number
result[nums.len() - 1 - i] *= right;
right *= nums[nums.len() - 1 - i];
}
result
}
}
fn main() {
assert_eq!(
Solution::product_except_self(vec![1, 2, 3, 4]),
vec![24, 12, 8, 6]
);
assert_eq!(
Solution::product_except_self(vec![-1, 1, 0, -3, 3]),
vec![0, 0, 9, 0, 0]
)
}

View File

@@ -0,0 +1,25 @@
// Accepted
// Runtime: 1 ms
// Memory Usage: 35.8 MB
// Submitted: January 14th, 2021
class Solution {
public int reverse(int x) {
// Remember whether it was negative or not
boolean negative = x < 0;
x = Math.abs(x);
int reversed = 0;
int degree = (int) Math.floor(Math.log10(x));
while (x > 0) {
// digit x 10^degree
reversed += Math.pow(10, degree--) * (x % 10);
x /= 10;
}
if (reversed == Integer.MAX_VALUE || reversed == Integer.MIN_VALUE)
return 0;
return negative ? -reversed : reversed;
}
}

View File

@@ -0,0 +1,35 @@
// Accepted
// Runtime: 4ms
// Memory Usage: 39.3 MB
// Submitted: January 15th, 2021
class Solution {
Map<Character, Integer> convert = new HashMap<Character, Integer>();
public Solution() {
char[] symbols = new char[]{'I', 'V', 'X', 'L', 'C', 'D', 'M'};
int[] values = new int[]{1, 5, 10, 50, 100, 500, 1000};
for (int i = 0; i < symbols.length; i++)
convert.put(symbols[i], values[i]);
}
public int romanToInt(String s) {
int n = s.length();
int sum = 0;
int prev = convert.get(s.charAt(0));
int cur = 0;
for (int i = 1; i < n; i++) {
cur = convert.get(s.charAt(i));
if (prev < cur)
cur -= prev;
else
sum += prev;
prev = cur;
}
sum += prev;
return sum;
}
}

View File

@@ -0,0 +1,27 @@
// Accepted
// Runtime: 4 ms
// Memory Usage: 39.1 MB
// Submitted: January 15th, 2021
class Solution {
public int[] frequencySort(int[] nums) {
Map<Integer, Integer> count = new HashMap<Integer, Integer>();
for (int n : nums)
count.put(n, count.getOrDefault(n, 0) + 1);
PriorityQueue<Map.Entry<Integer, Integer>> pq = new PriorityQueue<>((a, b) -> a.getValue() != b.getValue() ? a.getValue() - b.getValue() : b.getKey() - a.getKey());
pq.addAll(count.entrySet());
int[] sorted = new int[nums.length];
int i = 0;
while(!pq.isEmpty()) {
Map.Entry<Integer, Integer> entry = pq.poll();
int k = entry.getKey();
int v = entry.getValue();
while (v-- > 0)
sorted[i++] = k;
}
return sorted;
}
}

View File

@@ -0,0 +1,31 @@
// Accepted
// Runtime: 10 ms
// Memory Usage: 40 MB
// Submitted: January 14th, 2021
class Solution {
public String frequencySort(String s) {
// Get each character's frequency
Map<Character, Integer> count = new HashMap<Character, Integer>();
for (char c : s.toCharArray())
count.put(c, count.getOrDefault(c, 0) + 1);
// Paired with the character, sort each frequency
PriorityQueue<Map.Entry<Character, Integer>> pq = new PriorityQueue<>((a, b) -> b.getValue() - a.getValue());
pq.addAll(count.entrySet());
// Building the final st
StringBuilder sb = new StringBuilder();
while (!pq.isEmpty()) {
Map.Entry entry = pq.poll();
char v = (char) entry.getKey();
int n = (int) entry.getValue();
// Place n many v chars in the StringBuilder
for (int i = 0; i < n; i++)
sb.append(v);
}
return sb.toString();
}
}

View File

@@ -0,0 +1,34 @@
// Accepted
// Runtime: 1 ms
// Memory Usage: 39.3 MB
// Submitted: January 15th, 2021
class Solution {
public int specialArray(int[] nums) {
// Get the largest integer in the array
int max = nums[0];
for (int i = 1; i < nums.length; i++)
if (nums[i] > max)
max = nums[i];
for (int i = 0; i <= max; i++) {
int count = 0;
// Count the number of integers greater than or equal
for (int j = 0; j < nums.length; j++) {
if (nums[j] >= i)
count++;
// If we go over, stop counting
if (count > i)
break;
}
// If it's equal, we found our answer
if (count == i)
return i;
}
return -1;
}
}

View File

@@ -0,0 +1,32 @@
// Accepted
// Runtime: 1 ms
// Memory Usage: 38.9 MB
// Submitted: January 14th, 2021
class Solution {
public int myAtoi(String s) {
int sign = 1;
int i = 0;
int result = 0;
if (s.length() == 0) return 0;
// Skip through whitespace
while (i < s.length() && s.charAt(i) == ' ')
i++;
// If there is a sign present, extract it
if (i < s.length() && (s.charAt(i) == '-' || s.charAt(i) == '+'))
if (s.charAt(i++) == '-')
sign = -1;
while (i < s.length() && Character.isDigit(s.charAt(i))) {
if (result > Integer.MAX_VALUE / 10 || (result == Integer.MAX_VALUE / 10 && s.charAt(i) - '0' > Integer.MAX_VALUE % 10)) {
return (sign == 1) ? Integer.MAX_VALUE : Integer.MIN_VALUE;
}
result = (result * 10) + (s.charAt(i++) - '0');
}
return result * sign;
}
}

View File

@@ -0,0 +1,18 @@
// Accepted
// Runtime: 0 ms
// Memory Usage: 39.7 MB
// Submitted: January 12th, 2021
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[] { map.get(complement), i };
}
map.put(nums[i], i);
}
throw new IllegalArgumentException("No two sum solution");
}
}

View File

@@ -0,0 +1,36 @@
// Accepted
// Runtime: 4 ms
// Memory Usage: 39.8 MB
// Submitted: January 13th, 2021
class Solution {
public String convert(String s, int numRows) {
if (numRows == 1)
return s;
// Declare and instantiate with empty strings
StringBuilder[] levels = new StringBuilder[numRows];
for (int i = 0; i < levels.length; i++)
levels[i] = new StringBuilder();
int j = 1; // Start at 1 decrementing since it moves forward immediately before recording
boolean direction = false; // true = increment, false = decrement
for (int i = 0; i < s.length(); i++) {
// If hitting the top or bottom, set direction accordingly
if (j == 0)
direction = true;
else if (j == numRows - 1)
direction = false;
// Increment or decrement based on the direction
j += direction ? 1 : -1;
levels[j].append(s.charAt(i));
}
StringBuilder compile = new StringBuilder();
for (StringBuilder level : levels) {
compile.append(level);
}
return compile.toString();
}
}