Swift算法面试题2022(附答案)

1、 实现二分查找算法,如:[2,5,7,9,11,13,14,16],target为14,输出6。

func binarySearchWithoutRecursion(_ inputs: [Int], _ low: inout Int, _ high: inout  Int, _ target: Int) -> Int {
	while (low <= high) {
          let mid = low + (high - low) / 2;
          if (inputs[mid] > target) {
              high = mid - 1;
          } else if (inputs[mid] < target) {
                low = mid + 1;
          } else {
               //找到目标
               return mid;
          }
       }
       return -1;
}
        
func binarySearch(_ inputs: [Int], _ low: Int, _ high: Int, _ target: Int)  -> Int {
      let mid = low + (high - low) / 2;

      if(low > high) {
         return -1;
      } else{
           if(inputs[mid] == target) {
              return mid;
           } else if(inputs[mid] > target) {
               return binarySearch(inputs, low, mid-1, target);
           } else {
                return binarySearch(inputs, mid+1, high, target);
           }
      }
}
        

2、 冒泡排序:对以下一组数据进行降序排序。“24,17,85,13,9,54,76,45,5,63”

func bubbleSort(_ arr: inout [Int]) {
    let count = arr.count
    for index in 0..<count {
        var exchanged = false
        for j in 0..<(count - 1 - index) {
             if arr[j] < arr[j+1] {
                arr.swapAt(j, j+1)
                exchanged = true
             }
         }
         if !exchanged {
            break
         }
    }
}

// test result
var sortArr = [24, 17, 85, 13, 9, 54, 76, 45, 5, 63]
bubbleSort(&sortArr)
print(sortArr)      

3、 选择排序:对以下一组数据进行升序排序。“86, 37, 56, 29, 92, 73, 15, 63, 30, 8”

func selectSort(_ arr: inout [Int]) {
    let count = arr.count
    var min = 0
    for index in 0..<count-1 {
        min = index
        for j in index+1..<count {
             if arr[min] > arr[j] {
                 min = j
             }
        }
        if min != index {
              arr.swapAt(index, min)
        }
     }
}
      
// test result       
var selectSortArr = [86, 37, 56, 29, 92, 73, 15, 63, 30, 8]
selectSort(&selectSortArr)
print(selectSortArr)

4、快速排序:对以下数据进行降序排序。“24,17,85,13,9,54,76,45,5,63”

func fastSort(_ arr: inout [Int],  _ left: Int, _ right: Int) {
    if(left >= right) {
        return
    }

    var i = left

    var j = right

    let key = arr[left]

    while (i < j) {
        while (i < j && key >= arr[j]) {
            j = j - 1
        }

        if (i < j) {
            arr[i] = arr[j]
        }
        
        while (i < j && key < arr[i]) {
            i = i + 1
        }

        if (i < j) {
            arr[j] = arr[i]
        }
    }

    arr[i] = key

    fastSort(&arr, left, i-1)

    fastSort(&arr, i+1, right)
}

5、如何实现一个数组每个元素依次向右移动k位,后面的元素依次往前面补。比如: [1, 2, 3, 4, 5] 移动两位变成[4, 5, 1, 2, 3]。
思路:三次反转
后K位反转:12354
前部分反转:32154
整体全部反转:45123

func reversedK(_ arr: inout [Int], _ start: Int, _ end: Int) {
    var s = start, e = end
    while s < e {
       arr.swapAt(s, e)
       s += 1
       e -= 1
     }
}
        
func moveK(_ arr: inout [Int], _ k:Int) {
    let count = arr.count
    reversedK(&arr, count - k, count - 1)
    reversedK(&arr, 0, count - k - 1)
    reversedK(&arr, 0, count - 1)
}

// test result
var exampleArr = [1,2,3,4,5]
moveK(&exampleArr, 3)
print(exampleArr)

6、 给定一个字符串,输出本字符串中只出现一次并且最靠前的那个字符的位置?如“abaccddeeef”,字符是b,输出应该是2。

func findChar(_ inputStr: String) -> Int {
	if inputStr.count == 1 {
         return 0
    	}
     var tempDic = Dictionary<Character, Int>()
     inputStr.forEach { (ch) in
          if tempDic[ch] != nil {
             tempDic[ch] = tempDic[ch]! + 1
          } else {
             tempDic[ch] = 1
          }
	}
            
     for index in 0..<inputStr.count {
          let ch = inputStr[inputStr.index(inputStr.startIndex,offsetBy: index)]
          if tempDic[ch] == 1 {
              return index
          }
       }
            
     return -1
}

7、如何实现链表翻转(链表逆序)?

思路:每次把第二个元素提到最前面来。

class Node {
  var value: Int
  var next: Node?
        
  init(value: Int, next: Node? = nil) {
      self.value = value
      self.next = next
   }
}
    
func createLinkList(length: Int) -> Node? {
     if length <= 0 {
        return nil
     }
     let head = Node.init(value: 0)
     var number = 1, p = head, q = head
     while number <= length {
         p = Node.init(value: number)
         q.next = p
         q = p
         number += 1
      }
     return head
}
    
func printLinkList(head:Node?) {
   if head == nil {
      return
    }
    var p = head
    while p != nil {
       print("num = \(p!.value)")
       p = p?.next
    }
}
    
func reverseFuncLinkList(head:Node?) -> Node? {
   if head == nil {
      return head
   }
        
   var p = head
   var q: Node?
   while p != nil {
       let pNext = p?.next
       p?.next = q
       q = p
       p = pNext
    }
    return q
}

// create link list
var head = createLinkList(length: 5)
printLinkList(head: head)

// reverse link list
head = reverseFuncLinkList(head: head)
printLinkList(head: head)

8、链表:删除链表中的重复元素,每个重复元素需要出现一次。

给定链表:1->2->2->3->4->5->5

输出结果应当为 1->2->3->4->5

请实现下面的deleteRepeatElements函数:

func deleteRepeatElements(head:Node?) -> Node? {
    if head == nil {
       return head
    }
    var pNode = head
    while pNode != nil && pNode?.next != nil {
    	 if pNode?.value == pNode?.next?.value {
        	let tempNode = pNode?.next
        	pNode?.next = tempNode?.next
   	 } else {
       	pNode = pNode?.next
    	 }
    }
    return head
}

9、链表:删除链表中重复的元素,只保留不重复的结点。

给定链表:1->1->2->3->4->4->5

输出结果:2->3->5

请实现下面的deleteRepeatElements函数。

func deleteRepeatElements(head:Node?) -> Node? {
        if head == nil {
            return head
        }
        
        // 头结点有可能被删除
        let pHead = Node.init(value: 0)
        pHead.next = head
        var cur = pHead
        
        while cur.next != nil && cur.next?.next != nil {
            if cur.next?.value == cur.next?.next?.value {
                var tempNode = cur.next
                // 找到下一个没有重复的节点
                while tempNode != nil && tempNode?.next != nil && tempNode?.value == tempNode?.next?.value {
                    tempNode = tempNode?.next
                }
                cur.next = tempNode?.next
            } else {
                cur = cur.next!
            }
        }
        
        return pHead.next
}

10、链表:两个数相加,如给定[3,6,8]、[5,8,1],输出:[8,4,0,1],链表节点中的value范围是0-9

func addTwoNums(_ node1: Node?, _ node2: Node?) -> Node? {
        let node3:Node? = Node.init(value: 0)
        var pNode = node1
        var qNode = node2
        var rNode = node3
        
        var q = 0, r = 0
        while pNode != nil && qNode != nil {
            let sumRes = (pNode?.value ?? 0) + (qNode?.value ?? 0) + q
            (q, r) = sumRes.quotientAndRemainder(dividingBy: 10)
            rNode?.next = Node.init(value: r)
            pNode = pNode?.next
            qNode = qNode?.next
            rNode = rNode?.next
        }
        
        if q > 0 {
            rNode?.next = Node.init(value: q)
        }
        
        return node3?.next
}
参考资料

完整优秀版请移步小专栏:
Swift算法面试题2022(附答案)

更多好文推荐,扫描下方的二维码,关注《iOS开发秘籍》公众号,点关注不迷路!
在这里插入图片描述

本文内容中部分来自网络,后续会持续更新完善。欢迎一起学习交流!

如需转载,请注明出处

Swift算法面试题2022(附答案)

<think>嗯,用户现在想要了解SwiftUI的面试题答案。我需要先确定用户的具体需求。他们可能是在准备iOS开发职位面试,特别是涉及SwiftUI的部分。用户之前询问过回调地狱,所以可能已经有一定的Swift和异步编程经验,现在希望扩展SwiftUI的知识。 首先,我得整理常见的SwiftUI面试题,涵盖基础概念、布局、数据流、高级特性等方面。同时,答案需要准确且简明,帮助用户快速复习重点。还要注意面试题可能涉及实际应用场景,比如状态管理、动画实现、与UIKit的集成等。 用户可能期望的问题类型包括:解释SwiftUI的核心概念,比如声明式语法;比较SwiftUI和UIKit的区别;如何处理数据绑定和状态管理;常用修饰符的作用;布局系统的理解;以及调试和测试方法等。此外,可能需要包括一些代码示例,比如使用@State、@Binding、ObservableObject等。 另外,用户可能对性能优化、自定义视图、Combine框架的集成等问题感兴趣。需要确保答案不仅正确,还能展示最佳实践和常见陷阱,比如避免在视图体内执行繁重操作,如何高效更新UI等。 还要考虑用户可能的后续问题,比如如何处理复杂动画或与Core Data的集成,但现在先集中在常见的面试题上。需要结构化回答,分点列出问题和答案,便于用户理解和记忆。可能还需要比较不同的数据流工具,比如@StateObject和@ObservedObject的区别,或者EnvironmentObject的使用场景。 最后,要确保使用中文,符合用户的要求,并且格式清晰,避免Markdown,但保持段落和代码示例的清晰分隔。需要检查每个答案的准确性,避免错误,比如正确解释SwiftUI的生命周期方法,或者如何预览视图的不同方式。</think>以下是针对 **SwiftUI 面试题**的常见问题及参考答案,涵盖基础、进阶和实际应用场景,帮助系统性准备面试: --- ### 一、基础概念 #### 1. **SwiftUI 的核心特点是什么?** - **答案**: SwiftUI 是 Apple 的**声明式 UI 框架**,特点包括: - **声明式语法**:通过描述 UI 的最终状态,而非逐步操作视图。 - **实时预览**:Xcode 提供实时预览,无需编译运行即可查看 UI 变化。 - **跨平台**:支持 iOS、macOS、watchOS 和 tvOS。 - **数据驱动**:通过 `@State`、`@Binding` 等属性包装器自动同步数据与 UI。 --- #### 2. **SwiftUI 中 `@State` 和 `@Binding` 的区别?** - **答案**: - **`@State`**: 用于**视图内部**的私有状态管理,值变化时触发视图更新。 ```swift struct CounterView: View { @State private var count = 0 // 仅当前视图使用 var body: some View { Button("点击 \(count)") { count += 1 } } } ``` - **`@Binding`**: 用于**父子视图间共享状态**,传递对某个状态的引用。 ```swift struct ParentView: View { @State private var text = "" var body: some View { ChildView(text: $text) // 传递 Binding } } struct ChildView: View { @Binding var text: String var body: some View { TextField("输入", text: $text) } } ``` --- ### 二、布局与修饰符 #### 3. **解释 SwiftUI 的布局过程** - **答案**: SwiftUI 布局分为三步: 1. **父视图提议尺寸**:父视图向子视图提供一个可用空间(Proposed Size)。 2. **子视图计算需求**:子视图根据内容返回自身需求尺寸(Intrinsic Size)。 3. **父视图放置子视图**:父视图根据子视图需求,决定最终位置和大小。 **示例**: ```swift HStack { // 父视图 Text("Hello") // 子视图1 Text("World") // 子视图2 } ``` --- #### 4. **如何让视图占满剩余空间?** - **答案**: 使用 `.frame(maxWidth: .infinity, maxHeight: .infinity)` 修饰符: ```swift VStack { Text("顶部") Spacer() // 占满剩余空间 Text("底部") } .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color.gray) ``` --- ### 三、数据流与状态管理 #### 5. **`@ObservedObject` 和 `@StateObject` 的区别?** - **答案**: - **`@ObservedObject`**: 用于**外部传入的可观察对象**,不负责生命周期管理(可能被意外释放)。 - **`@StateObject`**: 由视图**持有并管理生命周期**,确保对象在视图更新时不被重建。 **代码示例**: ```swift class DataModel: ObservableObject { @Published var count = 0 } struct ContentView: View { @StateObject private var model = DataModel() // 正确方式 var body: some View { ChildView(model: model) } } struct ChildView: View { @ObservedObject var model: DataModel // 从父视图传入 var body: some View { Text("\(model.count)") } } ``` --- #### 6. **如何跨多层视图传递数据?** - **答案**: 使用 `@EnvironmentObject`: 1. **定义可观察对象**: ```swift class Settings: ObservableObject { @Published var isDarkMode = false } ``` 2. **注入到根视图**: ```swift @main struct MyApp: App { @StateObject var settings = Settings() var body: some Scene { WindowGroup { ContentView().environmentObject(settings) } } } ``` 3. **在子视图中访问**: ```swift struct ChildView: View { @EnvironmentObject var settings: Settings var body: some View { Toggle("深色模式", isOn: $settings.isDarkMode) } } ``` --- ### 四、高级特性 #### 7. **如何在 SwiftUI 中实现动画?** - **答案**: 使用 `.animation` 修饰符或 `withAnimation` 函数: ```swift struct AnimatedView: View { @State private var isScaled = false var body: some View { Button("缩放") { withAnimation(.easeInOut(duration: 0.3)) { isScaled.toggle() } } .scaleEffect(isScaled ? 1.5 : 1.0) } } ``` --- #### 8. **SwiftUI 如何与 UIKit 集成?** - **答案**: 通过 `UIViewRepresentable` 或 `UIViewControllerRepresentable` 协议: ```swift struct MyUIKitView: UIViewRepresentable { func makeUIView(context: Context) -> UIActivityIndicatorView { UIActivityIndicatorView(style: .large) } func updateUIView(_ uiView: UIActivityIndicatorView, context: Context) { uiView.startAnimating() } } // 使用 struct ContentView: View { var body: some View { MyUIKitView() } } ``` --- ### 五、常见陷阱 #### 9. **为什么视图不更新?** - **可能原因**: - 未使用 `@Published` 或 `@State` 等属性包装器。 - 直接修改结构体的值(应通过 `Binding` 或方法触发更新)。 - 在非主线程更新 UI(需确保数据操作在 `MainActor` 中)。 --- #### 10. **如何调试 SwiftUI 的布局问题?** - **技巧**: - 使用 `.border(Color.red)` 查看视图边界。 - 通过 `Self._printChanges()` 检查视图更新原因。 - 在 Xcode 中使用 **View Hierarchy Debugger**。 --- ### 六、面试加分点 - **性能优化**:理解 `LazyVStack` 与 `VStack` 的区别,避免不必要的视图重建。 - **自定义修饰符**:封装常用 UI 样式(如阴影、圆角)。 - **Combine 集成**:用 `@Published` 和 `sink` 实现响应式数据流。 - **预览技巧**:展示多设备、深色模式的预览配置。 掌握这些知识点,能系统性应对 SwiftUI 相关的面试问题!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值