Skip to content

Commit

Permalink
Implemented 'Find Target Indices After Sorting Array' challenge
Browse files Browse the repository at this point in the history
  • Loading branch information
wibosco committed Feb 25, 2024
1 parent 1fd5b7d commit 9fe5476
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 1 deletion.
5 changes: 5 additions & 0 deletions Algorithms/Algorithms/Algorithms/Searching/BinarySearch.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ struct BinarySearch {
}
}

//if target is smaller than all elements in values the right will have went to -1
guard right >= 0 else {
return nil
}

//only right can be used here
return values[right] == target ? right : nil
}
Expand Down
17 changes: 16 additions & 1 deletion Algorithms/AlgorithmsTests/Algorithms/BinarySearchTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,27 @@ final class BinarySearchTests: XCTestCase {
XCTAssertEqual(index, 3)
}

func test_findLastIndex_multipleIterations_valueNotFound() {
func test_findLastIndex_multipleIterations_valueIsInMidRange_valueNotFound() {
let values = [-17, -9, 0, 2, 3, 5, 7, 11, 13, 16, 16, 20, 22, 34, 78]

let index = BinarySearch.findLastIndex(of: 56, in: values)

XCTAssertNil(index)
}

func test_findLastIndex_multipleIterations_valueIsTooSmall_valueNotFound() {
let values = [-17, -9, 0, 2, 3, 5, 7, 11, 13, 16, 16, 20, 22, 34, 78]

let index = BinarySearch.findLastIndex(of: -100, in: values)

XCTAssertNil(index)
}

func test_findLastIndex_multipleIterations_valueIsToolarge_valueNotFound() {
let values = [-17, -9, 0, 2, 3, 5, 7, 11, 13, 16, 16, 20, 22, 34, 78]

let index = BinarySearch.findLastIndex(of: 100, in: values)

XCTAssertNil(index)
}
}
8 changes: 8 additions & 0 deletions LeetCode/LeetCode.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,8 @@
4311BC762A5866CB00137AED /* FindPivotIndexTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4311BC752A5866CB00137AED /* FindPivotIndexTests.swift */; };
4311BC782A586AC100137AED /* FindAllNumbersDisappearedInAnArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4311BC772A586AC100137AED /* FindAllNumbersDisappearedInAnArray.swift */; };
4311BC7A2A586AED00137AED /* FindAllNumbersDisappearedInAnArrayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4311BC792A586AED00137AED /* FindAllNumbersDisappearedInAnArrayTests.swift */; };
4314616F2B8B3959008683E1 /* FindTargetIndicesAfterSortingArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4314616E2B8B3959008683E1 /* FindTargetIndicesAfterSortingArray.swift */; };
431461712B8B398D008683E1 /* FindTargetIndicesAfterSortingArrayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 431461702B8B398D008683E1 /* FindTargetIndicesAfterSortingArrayTests.swift */; };
43147ED02A64103900802598 /* OptimalPartitionOfString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43147ECF2A64103900802598 /* OptimalPartitionOfString.swift */; };
43147ED22A64106E00802598 /* OptimalPartitionOfStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43147ED12A64106E00802598 /* OptimalPartitionOfStringTests.swift */; };
43147ED62A641C9E00802598 /* MinimumDifferenceBetweenHighestAndLowestOfKScore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43147ED52A641C9E00802598 /* MinimumDifferenceBetweenHighestAndLowestOfKScore.swift */; };
Expand Down Expand Up @@ -1491,6 +1493,8 @@
4311BC752A5866CB00137AED /* FindPivotIndexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindPivotIndexTests.swift; sourceTree = "<group>"; };
4311BC772A586AC100137AED /* FindAllNumbersDisappearedInAnArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindAllNumbersDisappearedInAnArray.swift; sourceTree = "<group>"; };
4311BC792A586AED00137AED /* FindAllNumbersDisappearedInAnArrayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindAllNumbersDisappearedInAnArrayTests.swift; sourceTree = "<group>"; };
4314616E2B8B3959008683E1 /* FindTargetIndicesAfterSortingArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindTargetIndicesAfterSortingArray.swift; sourceTree = "<group>"; };
431461702B8B398D008683E1 /* FindTargetIndicesAfterSortingArrayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindTargetIndicesAfterSortingArrayTests.swift; sourceTree = "<group>"; };
43147ECF2A64103900802598 /* OptimalPartitionOfString.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimalPartitionOfString.swift; sourceTree = "<group>"; };
43147ED12A64106E00802598 /* OptimalPartitionOfStringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimalPartitionOfStringTests.swift; sourceTree = "<group>"; };
43147ED52A641C9E00802598 /* MinimumDifferenceBetweenHighestAndLowestOfKScore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MinimumDifferenceBetweenHighestAndLowestOfKScore.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2072,6 +2076,7 @@
3D5C90E727A7F7620035C399 /* FindPeakElement.swift */,
4311BC732A58668100137AED /* FindPivotIndex.swift */,
3D5C90B127A7F7620035C399 /* FindSmallestLetterGreaterThanTarget.swift */,
4314616E2B8B3959008683E1 /* FindTargetIndicesAfterSortingArray.swift */,
43D8B8012A629C0000B3F197 /* FindTheDifferenceOfTwoArrays.swift */,
437119472A5F5232000E0EE5 /* FindTheIndexOfTheFirstOccurrenceInAString.swift */,
3D5C911027A7F7630035C399 /* FindTheTownJudge.swift */,
Expand Down Expand Up @@ -2530,6 +2535,7 @@
3D5C924A27A7F76C0035C399 /* FindPeakElementTests.swift */,
4311BC752A5866CB00137AED /* FindPivotIndexTests.swift */,
3D5C928F27A7F76C0035C399 /* FindSmallestLetterGreaterThanTargetTests.swift */,
431461702B8B398D008683E1 /* FindTargetIndicesAfterSortingArrayTests.swift */,
43D8B8032A629C3700B3F197 /* FindTheDifferenceOfTwoArraysTests.swift */,
437119492A5F528C000E0EE5 /* FindTheIndexOfTheFirstOccurrenceInAStringTests.swift */,
3D5C924527A7F76C0035C399 /* FindTheTownJudgeTests.swift */,
Expand Down Expand Up @@ -3210,6 +3216,7 @@
3D193ABB27C78D7100E49F08 /* CombinationSumIII.swift in Sources */,
3D5C916127A7F7630035C399 /* LowestCommonAncestorBinarySearchTree.swift in Sources */,
43F3DF3929E0B61600EDEB1C /* OddEvenLinkedList.swift in Sources */,
4314616F2B8B3959008683E1 /* FindTargetIndicesAfterSortingArray.swift in Sources */,
3D46242927E29BDB00A888C1 /* RemoveDuplicatesFromSortedList.swift in Sources */,
3D5C91EF27A7F7630035C399 /* DivideTwoIntegers.swift in Sources */,
436634982AFE5C320087F13F /* IncreasingOrderSearchTree.swift in Sources */,
Expand Down Expand Up @@ -3757,6 +3764,7 @@
3D5C92BE27A7F76C0035C399 /* PeakIndexMountainArrayTests.swift in Sources */,
3DB7C5CF27CD480200353EED /* MovingAverageTests.swift in Sources */,
4311BC722A585E2400137AED /* IsomorphicStringsTests.swift in Sources */,
431461712B8B398D008683E1 /* FindTargetIndicesAfterSortingArrayTests.swift in Sources */,
435B70AE2B0513BF003D51CA /* ReverseOddLevelsOfBinaryTreeTests.swift in Sources */,
43313BC529D8EBAB005FCF5D /* BullsAndCowsTest.swift in Sources */,
43BD45802AFCCFE2006216F0 /* SumRootToLeafNumbersTests.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//
// FindTargetIndicesAfterSortingArray.swift
// LeetCode
//
// Created by William Boles on 25/02/2024.
//

import Foundation

//https://leetcode.com/problems/find-target-indices-after-sorting-array/
struct FindTargetIndicesAfterSortingArray {

//Time: O(n log n) where n is the number of elements in `nums`
//Space: O(n)
//array
//sorting
//binary search
//
//Solution Description:
//With a sorted array of `nums` we can perform two binary searches to find the first occurrence of `target` and the last
//occurrence. With these two indexes we can construct the result array from that range.
//
//N.B. Both `leftMostIndex` and `rightMostIndex` might have the same index value or they both might be nil but one can't
//be nil while the other is non-nil.
func targetIndices(_ nums: [Int], _ target: Int) -> [Int] {
let sortedNums = nums.sorted(by: <)

let leftMostIndex = firstOccurrence(sortedNums, target)
let rightMostIndex = lastOccurrence(sortedNums, target)

guard let leftMostIndex = leftMostIndex, let rightMostIndex = rightMostIndex else {
return [Int]()
}

return Array(leftMostIndex...rightMostIndex)
}

private func firstOccurrence(_ values: [Int], _ target: Int) -> Int? {
var left = 0
var right = values.count - 1

var result: Int?

while left <= right {
let mid = left + (right - left) / 2 //to avoid overflow

if values[mid] == target {
result = mid
right = mid - 1
} else if values[mid] > target {
right = mid - 1
} else {
left = mid + 1
}
}

return result
}

private func lastOccurrence(_ values: [Int], _ target: Int) -> Int? {
var left = 0
var right = values.count - 1

var result: Int?

while left <= right {
let mid = left + (right - left) / 2 //to avoid overflow

if values[mid] == target {
result = mid
left = mid + 1
} else if values[mid] < target {
left = mid + 1
} else {
right = mid - 1
}
}

return result
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//
// FindTargetIndicesAfterSortingArrayTests.swift
// LeetCodeTests
//
// Created by William Boles on 25/02/2024.
//

import XCTest

@testable import LeetCode

final class FindTargetIndicesAfterSortingArrayTests: XCTestCase {

//MARK: - Tests

func test_A() {
let nums = [1,2,5,2,3]
let target = 2

let result = FindTargetIndicesAfterSortingArray().targetIndices(nums, target)

XCTAssertEqual(result, [1,2])
}

func test_B() {
let nums = [1,2,5,2,3]
let target = 3

let result = FindTargetIndicesAfterSortingArray().targetIndices(nums, target)

XCTAssertEqual(result, [3])
}

func test_C() {
let nums = [1,2,5,2,3]
let target = 5

let result = FindTargetIndicesAfterSortingArray().targetIndices(nums, target)

XCTAssertEqual(result, [4])
}

func test_D() {
let nums = [1,2,5,2,3]
let target = 7

let result = FindTargetIndicesAfterSortingArray().targetIndices(nums, target)

XCTAssertEqual(result, [Int]())
}

func test_E() {
let nums = [48,90,9,21,31,35,19,69,29,52,100,54,21,86,6,45,42,5,62,77,15,38]
let target = 6

let result = FindTargetIndicesAfterSortingArray().targetIndices(nums, target)

XCTAssertEqual(result, [1])
}

func test_F() {
let nums = [19,35,87,45,93,10,79,41,57,75,66,56,74,25,59,71,19,18,84,28,32,63,73,97,53]
let target = 8

let result = FindTargetIndicesAfterSortingArray().targetIndices(nums, target)

XCTAssertEqual(result, [Int]())
}
}

0 comments on commit 9fe5476

Please sign in to comment.