Adventures in Leetcode: PowerShell + Leetcode
PowerShell, Leetcode ·Adventures in Leet Code: PowerShell Twist
I’ve been looking into new challenges recently and decided to give LeetCode a shot. I quickly realized that I haven’t been working on this kind of problem since I took a couple programming classes where I didn’t learn much. Leetcode doesn’t support PowerShell, so I’m going to post these here and if anyone has any constructive feedback I’d appreciate it if you shared it in the comments below.
I found that I was having to look up things that I haven’t encountered much while using PowerShell. I really enjoy how these are pushing me to grow. This blog post aims to share some problems and solutions that I’ve worked on.
Useful Constructs
For Loops
A For
loop is a great way to iterate on a subset of a collection of items. Oftentimes, foreach
is more appropriate, but I’ve found the for loop to be useful in a lot of leetcode questions.
# Reverse a string with a for loop
$string = 'Jill loves cars.'
# make sure to use the length property instead of count when dealing with manipulating characters in a string
$output = for ($i = 1 ; $i -le $string.length; $i++) {
$string[-$i] # output each character, starting at the back
}
# $output is an array, rather than a string. We need to -join them back together again <3
$output -join ''
Problems
Add Binary Strings
Given two binary strings a and b, return their sum as a binary string.
Example 1:
Input: a = “11”, b = “1” Output: “100”
My Solution
function Convert-BinaryStringtoInteger {
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[int]$a,
[Parameter(Mandatory)]
[int]$b
)
$aInt = [Convert]::ToInt32($a,2)
$bInt = [Convert]::ToInt32($b,2)
$cInt = $aInt + $bInt
$cBinaryString = [Convert]::ToString($cInt,2)
Write-Output $cBinaryString
}
Test it
Convert-BinaryStringtoInteger -a 11 -b 1
100
Convert-BinaryStringtoInteger -a 1010 -b 1011
10101
2 - Remove All Adjacent Duplicates In String
Problem
https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string/
Remove All Adjacent Duplicates In String. You are given a string s consisting of lowercase English letters. A duplicate removal consists of choosing two adjacent and equal letters and removing them.
We repeatedly make duplicate removals on s until we no longer can.
Return the final string after all such duplicate removals have been made. It can be proven that the answer is unique.
My Solution
function Remove-AdjacentDuplicates {
param(
[Parameter(Mandatory)]
[ValidateScript({
if (-not ($_ -cmatch '[a-z]')) {
throw 'lowercase English letters only'
}
else { $true }
})]
[ValidateLength(1, 100000)]
[string]
$s
)
for ($i = 0; $i -lt $s.length ; $i++) {
if ($s[$i] -eq $s[$i + 1]) {
$stringToReplace = "$($s[$i])$( $s[ $i + 1 ])"
$s = $s.replace($stringtoReplace, '')
$i = -1 # set to negative because it get +1 every iteration and we want it to be on 0
}
}
Write-Output $s
}
Test it
Remove-AdjacentDuplicates -s abbaca
ca
Remove-AdjacentDuplicates -s azxxzy
ay
3 - Valid Word Abbreviation
https://leetcode.com/problems/valid-word-abbreviation/
Given a string word and an abbreviation abbr, return whether the string matches the given abbreviation.
A substring is a contiguous non-empty sequence of characters within a string.
My Solution
function Test-ValidWordAbbreviation {
param(
[Parameter(Mandatory)]
[ValidateLength(1, 20)]
[ValidateScript({
if ($_ -cmatch '[a-z]0') {
throw "No leading zeros"
}
if ($_ -cmatch '[A-Z]') {
throw "No capital letters"
}
else { $true }
})]
[string]$Word,
[Parameter(Mandatory)]
[ValidateLength(1, 10)]
[string]$Abbr
)
$replacedAbbr = $Abbr
$pattern = '\d{1,}' # 1 or more digits
$matches = [regex]::Matches($replacedAbbr , $pattern)
for ($i = 0; $i -lt $matches.Count; $i++) {
$numbers = [regex]::Matches($replacedAbbr , $pattern)
[int]$upperBound = $numbers[0].Index + $numbers[0].value - 1
$replacementText = $word[ $numbers[0].index..$upperBound ] -join ''
$replacedAbbr = $replacedAbbr.Replace( $numbers[0].Value , $replacementText )
}
if ($replacedAbbr -eq $Word) { Write-Output $true }
else { Write-Output $false }
}
Test it
Test-ValidWordAbbreviation -Word internationalization -Abbr i12iz4n
True
Test-ValidWordAbbreviation -Word a2e -Abbr apple
False
4 - Valid Palindrome II
https://leetcode.com/problems/valid-palindrome-ii/
Given a string s, return true if the s can be palindrome after deleting at most one character from it.
My Solution
function Test-ValidPalindromeII {
param(
[Parameter(Mandatory)]
[ValidateLength(1, 100000)]
[ValidateScript({
if ($_ -cmatch '[A-Z]') {
throw 'lowercase English letters only'
}
else {
Write-Output $true
}
})]
[string]
$s
)
# See if it's a palindrome as-is
$reversedWord = for ($j = 1; $j -le $s.length; $j++) {
$s[ - $j ]
}
$reversedWord = $reversedWord -join ''
if ($reversedWord -eq $s) { $Palindrome = $true }
# Iterate through and remove a character then test if it's a palindrome
for ($i = 0; $i -lt $s.length; $i++) {
# break from loop if $Palindrome is set to $true
if ($Palindrome) { break }
$replacedWord = $s.remove($i, 1)
$reversedWord = for ($j = 1; $j -le $replacedWord.length; $j++) {
$replacedWord[ - $j ]
}
$reversedWord = $reversedWord -join ''
if ($reversedWord -eq $replacedWord) {
$Palindrome = $true
}
}
if ($Palindrome) {
Write-Output $true
}
else { Write-Output $false }
}
Test it
Test-ValidPalindromeII -s 'aba'
True
Test-ValidPalindromeII -s 'abca'
True
Test-ValidPalindromeII -s 'abc'
False
5 - Valid Phone Number
https://www.interviewbit.com/problems/valid-phone-number/
Given a text file input that contains list of phone numbers (one per line).
Write a bash script to print all valid phone numbers.You may assume that a valid phone number must appear in one of the following two formats:
(xxx) xxx-xxxx xxx-xxx-xxxx You may also assume each line in the text file must not contain leading or trailing white spaces.
function Get-ValidPhoneNumber {
param(
[Parameter(Mandatory)]
[string[]]$Numbers
)
foreach($number in $Numbers){
if ($number -match '^\(\d{3}\) \d{3}-\d{4}$'){
Write-Output $number
}
if ($number -match '^\d{3}-\d{3}-\d{4}$') {
Write-Output $number
}
}
}
Test It
$numbers = "987-123-4567", "123 456 7890","(123) 456-7890"
Get-ValidPhoneNumber -Numbers $numbers
6 - Lines in a given range
Write a bash script to print all the lines of the input which are in the given range. The first line of the input contains two integers l and r separated by space. You have to print all the lines of the file input which are in the range of [l, r].
function Get-LinesinGivenRange {
param(
[Parameter(Mandatory)]
[string[]]
$InputContent
)
$ranges = ($InputContent -split "`n")[0].trim() -split ' '
$InputContent = $InputContent -split "`n"
$InputContent[( $range[0] -1 )..( $range[1] -1 )]
}
Test It
$content = "10 15
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8
Line 9
Line 10
Line 11
Line 12
Line 13
Line 14
Line 15
Line 16
Line 17
Line 18
Line 19
Line 20"
Get-LinesinGivenRange -Input $content -Range 10,15
7 - Remove Punctuations
https://www.interviewbit.com/problems/remove-punctuations/
Write a bash script that removes all the punctuations in the given file named input For this question, assume that all of the following symbols are punctuations: ! @ # $ % ^ & * ( ) _ - + = { } [ ] ; : ‘ “ ` / > ? . , < ~ | \
Example:
Assume that input has the following content:
This’s the sunny day. It is the sunny day, we can go out. Your script should output the following:
Thiss the sunny day It is the sunny day we can go out
My Solution
function Remove-Punctuation {
param(
[Parameter(Mandatory)]
[string]
$InputContent
)
$characters = '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '-', '+', '=', '{', '}', '[', ']', ';', ':', "'", '"', '`', '/', '>', '?', '.', ',', '<', '~', '|', '\'
$characters | Foreach-Object {
$InputContent = $InputContent.replace($_, '')
}
Write-Output $InputContent
}
Test it
$string = "This's the sunny day.
It is the sunny day, we can go out."
Remove-Punctuation -InputContent $string
Thiss the sunny day
It is the sunny day we can go out
8 - Majority Element
https://www.interviewbit.com/problems/majority-element
Given an array of size n, find the majority element. The majority element is the element that appears more than floor(n/2) times. You may assume that the array is non-empty and the majority element always exist in the array.
Example :
Input : [2, 1, 2] Return : 2 which occurs 2 times which is greater than 3/2.
My solution
function Get-Solution {
[CmdletBinding()]
param (
[int[]]$Numbers
)
$numbers | Where-Object {$_ -gt ($Numbers.count / 2) } | Select-Object -First 1
}
Test It
Get-Solution -Numbers 2,1,2
2
9 - Reverse Words in a String
https://leetcode.com/problems/reverse-words-in-a-string/
Given an input string s, reverse the order of the words.
A word is defined as a sequence of non-space characters. The words in s will be separated by at least one space.
Return a string of the words in reverse order concatenated by a single space.
Note that s may contain leading or trailing spaces or multiple spaces between two words. The returned string should only have a single space separating the words. Do not include any extra spaces.
My Solution
function Reverse-WordsinString {
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string]$S
)
$words = ($S -split ' ').trim() # Split the words and remove extra spaces
# the skye is blue
$output = for ($i = 1; $i -le $words.count; $i++){
$words[-$i] | Where-Object {$_ -Match '\w'} # only grab words, not blank lines
}
$output -join ' '
}
Test It
Reverse-WordsinString -S "the skye is blue"
blue is skye the
Reverse-WordsinString -S " Bob Loves Alice "
Alice Loves Bob
Reverse-WordsinString -S "Alice does not even like bob"
bob like even not does Alice
10 - Word Break
https://leetcode.com/problems/word-break/
Given a string s and a dictionary of strings wordDict, return true if s can be segmented into a space-separated sequence of one or more dictionary words.
Note that the same word in the dictionary may be reused multiple times in the segmentation.
Example 1:
Input: s = “leetcode”, wordDict = [“leet”,”code”] Output: true Explanation: Return true because “leetcode” can be segmented as “leet code”. Example 2:
Input: s = “applepenapple”, wordDict = [“apple”,”pen”] Output: true Explanation: Return true because “applepenapple” can be segmented as “apple pen apple”. Note that you are allowed to reuse a dictionary word. Example 3:
Input: s = “catsandog”, wordDict = [“cats”,”dog”,”sand”,”and”,”cat”] Output: false
My Solution
function Test-WordBreak {
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string]$s,
[Parameter(Mandatory)]
[string[]]$WordDict
)
$remainingWords = $s
foreach ($word in $WordDict ) {
$remainingWords = $remainingWords -split $word
}
if ( ( $remainingWords | Where-Object { $_ -match '\w' }) -gt 0) {
return $false
}
else {
return $true
}
}
Test it
test-wordbreak -s leetcode -worddict 'leet','code'
True
test-wordbreak -s applepenapple -worddict 'apple','pen'
True
test-wordbreak -s catsandog -WordDict 'cats','dog','sand','and','cat'
False