【问题标题】:Beginner Swift 3: How to find pairs in array that add up to given number初学者 Swift 3:如何在数组中找到加起来等于给定数字的对
【发布时间】:2021-02-10 13:35:35
【问题描述】:

需要遍历一个数组并判断是否有任何一对数的和为 8

例如[1,2,4,4] = 是的

可以让它与许多嵌套的 if 语句一起工作,但如果数组发生变化,这将是不切实际的。

我最理想的做法是对 i 说 if i + (i.indexPosition +1 {Number next to i})) == 8 然后打印 true,如果不是 false,然后进入下一个迭代数字集

想知道是否有人知道可以在这里使用的更好的逻辑?非常感谢!!

例如

var numbersSet = [1, 2, 4, 4]

for i in numbersSet2 {

    var targetSum = 8

    if i + numbersSet2[1] == targetSum {

        print("True")
    } else { // Nested if statements here

        print("False")
    }
}

【问题讨论】:

    标签: arrays swift sequence


    【解决方案1】:

    您想检查所有总和 numbers[i] + numbers[j] 其中 i < j,最简单的方法是这样的嵌套循环:

    func checkPairs(in numbers: [Int], forSum target: Int) -> Bool {
    
        for i in 0..<numbers.count {
            for j in i+1..<numbers.count {
                if numbers[i] + numbers[j] == target {
                    return true
                }
            }
        }
        return false
    }
    

    使用enumerated() 方法可以避免数组查找 和数组切片:

    func checkPairs(in numbers: [Int], forSum target: Int) -> Bool {
    
        for (i, x) in numbers.enumerated() {
            for y in numbers[i+1 ..< numbers.count] {
                if x + y == target {
                    return true
                }
            }
        }
        return false
    }
    

    这里x是外循环的当前元素,i是它的 指数。 y 是开始的内循环的当前元素 枚举i + 1

    例子:

    print(checkPairs(in: [1, 2, 4, 4], forSum: 8))
    print(checkPairs(in: [1, 2, 4, 4], forSum: 7))
    

    上述函数可以更简洁地写成

    func checkPairs(in numbers: [Int], forSum target: Int) -> Bool {
    
        return numbers.enumerated().contains(where: { (i, x) -> Bool in
            numbers[i+1 ..< numbers.count].contains(target - x)
        })
    }
    

    如果给定的数字是非递减的顺序,那么你可以 通过终止内部循环来提高性能 如果无法达到目标总和:

    func checkPairs(in numbers: [Int], forSum target: Int) -> Bool {
    
        for (i, x) in numbers.enumerated() {
            for y in numbers[i+1 ..< numbers.count] {
                if x + y == target {
                    return true
                }
                if x + y > target {
                    break
                }
            }
        }
        return false
    }
    

    对于非递减数的数组,效率更高 解决方案是对target - x 进行二分搜索 对于每个数组元素x。这是一个可能的二进制搜索 实现(https://stackoverflow.com/a/40226976/1187415 的变体):

    extension Collection where Iterator.Element: Comparable {
    
        func binarySearch(element: Iterator.Element) -> Bool {
            var low = startIndex
            var high = endIndex
            while low != high {
                let mid = index(low, offsetBy: distance(from: low, to: high)/2)
                if self[mid] < element {
                    low = index(after: mid)
                } else if element < self[mid] {
                    high = mid
                } else {
                    return true
                }
            }
            return false
        }
    }
    

    然后可以用作

    func checkPairs(in numbers: [Int], forSum target: Int) -> Bool {
    
        return numbers.enumerated().contains(where: { (i, x) -> Bool in
            numbers[i+1 ..< numbers.count].binarySearch(element: target - x)
        })
    }
    

    【讨论】:

      【解决方案2】:

      您可以使用带有索引的嵌套 for 循环:

      for (firstIndex, firstElement) in numbersSet.enumerated() {
          for (secondIndex, secondElement) in numbersSet.enumerated() {
              if firstIndex != secondIndex && firstElement + secondElement == 8 {
                  return true
              }
          }
      }
      

      【讨论】:

        【解决方案3】:

        以上所有答案都很好,但都返回 Bool 值,因此我正在编写解决方案,将所有可能的对存储在字典中并打印出来。

        以下解决方案将避免重复,从而将复杂性降至最低。

        var numbers = [13,2,4,5,6,3,7,90,11,10,12,1,8,9]
        var dictionary1 : [Int : Int] = [:]
        var j = 0
        func findPair(numbers : [ Int ] , number : Int) -> [Int : Int] {
            
            for (i , _) in numbers.enumerated() {
                
                j = i
                while j < numbers.count {
                    
                    if i != j {
                        let addition = numbers[i] + numbers[j]
                        if addition == number {
                            dictionary1[numbers[i]] = numbers[j]
                        }
                    }
                    j += 1
                }
            }
            return dictionary1
        }
        
        let result = findPair(numbers: numbers, number: 11)
        print(dictionary1)
        

        输出 - [10:1, 4:7, 5:6, 3:8, 2:9]

        这些都是以给定数字相加的对。即 11

        【讨论】:

          【解决方案4】:

          使用两个指针技术。

          时间复杂度:O(n)

          此处提到的其他解决方案具有时间复杂度:O(n2)

          func isPairSum()-> Bool{
          
          let array = [3, 5, 9, 2, 8, 10, 11]
          let sum = 22
          
          
          var i = 0
          var j = array.count - 1
          
          while i<j {
              
              let valueSum = array[i] + array[j]
              if valueSum == sum {
                  return true
              }
              
              else if valueSum > sum {
                  j -= 1
              }
              
              else if valueSum < sum {
                  i += 1
              }
              
          }
          return false
          

          }

          如果你想要这对的值,而不是返回 Bool,你可以返回 Int 类型的 Tuple。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-06-12
            • 2019-08-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-11-15
            相关资源
            最近更新 更多