高频面试算法:leetCode算法(swift实现二)

  • 1、算法一:删除重复的元素

    ///MARK: remove dulplicate
    ///给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
    ///由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
    ///将最终结果插入 nums 的前 k 个位置后返回 k 。
    ///不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
    func removeDunplicate(array:[Int]){
        let result = self.removeStartIndex(array: array)
        let removeStartIndex = result.1
        let resultArray = result.0.prefix(removeStartIndex)
        print("remove dulplicate: original:\(array) result:\(resultArray)")
    }
    
    ///MARK: get start index of remove in array
    func removeStartIndex(array:[Int]) -> ([Int],Int){
        guard array.count > 1 else{
            print("数组个数小于2个")
            return (array,array.count)
        }
        var arr = array
        let count = arr.count
        var j = 0
        for index in 1..<count{
            if arr[index] != arr[j]{
                j += 1
                arr[j] = arr[index]
            }
        }
        return (arr,j + 1)
    }
    
  • 2、算法二:盛最多水的容器

    ///给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
    ///找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
    ///返回容器可以储存的最大水量。
    ///说明:你不能倾斜容器
    func maxArea(array:[Int]){
        if array.count < 2{
            print("数据个数小于两个")
            return
        }
        var indexOne = 0
        var indexTwo = 0
        var area = 0
        for index in 1..<array.count{
            for inerIndex in 0..<index{
                let width = index - inerIndex
                let height = (array[index] - array[inerIndex]) < 0 ? array[index] : array[inerIndex]
                let tempArea = width * height
                if tempArea > area{
                    area = tempArea
                    indexOne = inerIndex
                    indexTwo = index
                }
            }
        }
        print("indexOne:\(indexOne)  indexTwo:\(indexTwo)     area:\(area)")
    }
    
  • 3、算法三:将0移动到末尾

    ///给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
    ///必须在不复制数组的情况下原地对数组进行操作。
    func moveZeros(arr:inout [Int]){
        var zeroIndex = 0
        var nonZeroIndex = 0
        print("moveZeros:original:\(arr)")
        let count = arr.count
        while(zeroIndex<count-1 && nonZeroIndex<count-1){
            while(zeroIndex<count && arr[zeroIndex] != 0){
                if nonZeroIndex <= zeroIndex{
                    nonZeroIndex += 1
                }
                zeroIndex += 1
            }
            while(nonZeroIndex<count && arr[nonZeroIndex] == 0){
                nonZeroIndex += 1
            }
            if zeroIndex < count && nonZeroIndex < count{
                arr[zeroIndex] = arr[nonZeroIndex]
                arr[nonZeroIndex] = 0
            }
            zeroIndex += 1
            nonZeroIndex += 1
        }
        print("moveZeros:result:\(arr)")
    }
    
  • 4、算法4

    ///将两个升序链表合并为一个新的 升序 链表并返回。
    ///新链表是通过拼接给定的两个链表的所有节点组成的。
    func mergeTwoLists(_ list1:MergeNode?, _ list2:MergeNode?) -> MergeNode?{
        if list1 == nil{
            return list2
        }
        if list2 == nil{
            return list1
        }
        
        var result = list1
        var node1 = list1
        var currNodeLast = list1
        var node2 = list2
        var tempNode2 : MergeNode?
        
        while(node2 != nil){
            if node2!.value < node1?.value ?? 0{
                if currNodeLast?.value != node1?.value{
                    currNodeLast?.next = node2
                }else{
                    result = node2
                }
                tempNode2 = node2?.next
                node2?.next = node1
                currNodeLast = node2
                node2 = tempNode2
            }else{
                currNodeLast = node1
                node1 = node1?.next
                if node1 == nil{
                    currNodeLast?.next = node2
                    break
                }
            }
        }
        return result
    }
    
    class MergeNode : NSObject{
        var value : Int = 0
        var next : MergeNode?
    }
    
  • 5、算法五

    ///给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。
    ///你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
    func swapPairs(_ head:MergeNode?) -> MergeNode?{
        var result = head
        var node1 = head
        var node2 = head?.next
        var tempNode : MergeNode?
        var isFirstExchange = true
        while(node1 != nil && node2 != nil){
            if isFirstExchange{
                result = node2
                isFirstExchange = false
            }
            node1?.next = node2?.next
            node2?.next = node1
            tempNode?.next = node2
            tempNode = node1
            
            node1 = node1?.next
            node2 = node1?.next
        }
        return result
    }
    
  • 6、算法六

    ///反转链表
    func reverseLink(_ head:MergeNode?) -> MergeNode?{
        if head == nil || head?.next == nil{
            return head
        }
        var node1 = head
        var node2 = head?.next
        var node3 = node2?.next
        
        node2?.next = node1
        node1?.next = nil
        if node3 == nil{
            
            return node2
        }
        
        while(node3 != nil){
            node1 = node3
            node3 = node3?.next
            node1?.next = node2
            node2 = node1
        }
        return node2
    }
    
    ///给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
    ///k 是一个正整数,它的值小于或等于链表的长度。
    ///如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
    ///进阶:
    ///你可以设计一个只使用常数额外空间的算法来解决此问题吗?
    ///你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
    //移动节点的方式
    func reverseKGroup(_ head:MergeNode?,_ k:Int) -> MergeNode?{
        var node = head
        var groupFisrtNode = head
        var nextGroupFirstNode : MergeNode?
        var lastGroupEndNode : MergeNode?
        var groupCount = 1
        var isFirstExchange = true
        var result = head
        while(node != nil){
            if groupCount == k{
                nextGroupFirstNode = node?.next
                node?.next = nil
                
                let reverseList = reverseLink(groupFisrtNode)
                if isFirstExchange{
                    result = reverseList
                    isFirstExchange = false
                }else{
                    lastGroupEndNode?.next = reverseList
                }
                
                lastGroupEndNode = groupFisrtNode
                groupFisrtNode?.next = nextGroupFirstNode
                groupCount = 1
                groupFisrtNode = nextGroupFirstNode
                node = nextGroupFirstNode
            }else{
                node = node?.next
                groupCount += 1
            }
        }
        return result
    }
    
  • 7、算法七

    ///给你一个链表的头节点 head ,判断链表中是否有环。
    ///如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
    ///如果链表中存在环 ,则返回 true 。 否则,返回 false 。
    ///使用龟兔赛跑赛跑的方式,龟:每次移动一个,兔:每次移动两个,最后如果兔子和龟相遇,说明会有循环
    func hasCycle(_ head:MergeNode?) -> Bool{
        var slow = head
        var fast = head?.next
        while(slow != nil){
            if slow == fast{
                return true
            }
            slow = slow?.next
            fast = fast?.next?.next
        }
        return false
    }
    

转载请标明出处

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值