LeetCode 1~10

训练思维,提高编程能力,不为刷题而刷题

1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。

Swift版本

class Solution {
    func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
        var map = [Int : Int]()
        
        for (i, e) in nums.enumerated() {
            if let u = map[target - e] {
                return [u, i]
            }else {
                map.updateValue(i, forKey: e)
            }
        }
        
        return []
    }
}

OC版本

- (NSArray *)twoSum:(NSArray <NSNumber *>*)nums target:(NSInteger)target {
    
    NSMutableDictionary *mutDic = [NSMutableDictionary dictionary];
    
    __block NSArray *result = nil;
    [nums enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSNumber *num = mutDic[@(target - obj.integerValue)];
        if (num) {
            result = @[num, @(idx)];
            *stop = YES;
        }else {
            mutDic[obj] = @(idx);
        }
    }];
    return result;
}

测试代码:

NSArray *testArr = [NSArray arrayWithObjects:@(2),@(7),@(11), @(15), nil];
    NSArray *resu = [self twoSum:testArr target:18];
    if (resu) {
        NSLog(@"找到结果:%ld, %ld", [resu[0] integerValue], [resu[1] integerValue]);
    }

2. 两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

Swift实现

class Solution {
    func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
        var listNode1 = l1;
        var listNode2 = l2;
        
        //进位
        var carry: Int = 0;
        
        let result: ListNode = ListNode(0)
        var currentNode = result
        
        while listNode1 != nil || listNode2 != nil || carry > 0 {
            let sum: Int = (listNode1?.val ?? 0) + (listNode2?.val ?? 0) + carry
            currentNode.next = ListNode(sum % 10)
            currentNode = currentNode.next!
            
            listNode1 = listNode1?.next
            listNode2 = listNode2?.next
            carry = sum / 10
        }
        
        return result.next
    }
}

OC实现

- (ListNode *)addTwoNumber:(ListNode *)l1 listNode2:(ListNode *)l2 {
    ListNode *result = [[ListNode alloc] initWithVal:0];
    ListNode *currentNode = result;
    
    ListNode *listNode1 = l1;
    ListNode *listNode2 = l2;
    
    //进位标记
    NSInteger carry = 0;
    
    while (listNode1 || listNode2 || carry > 0) {
        NSInteger sum = listNode1.val + listNode2.val + carry;
        currentNode.next = [[ListNode alloc] initWithVal:sum%10];
        currentNode = currentNode.next;
        
        listNode1 = listNode1.next;
        listNode2 = listNode2.next;
        carry = sum / 10;
    }
    
    return result.next;
}

3.无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

Swift

/*
 * 滑动窗口法
 */
func lengthOfLongestSubstring(_ s: String) -> Int {
        
        let strlen = s.count
        let chs: [Character] = Array(s)
    
        var map = [Character : Int]()
        var start = 0
        
        var maxLen: Int = 0
        for i in 0..<chs.count {
            let char = chs[i]
            if let preIdx = map[char] {
                start = max(start, preIdx+1)
            }
            
            map[char] = i;
            maxLen = max(maxLen, i-start+1)
            
            print(start, maxLen)
        }
        
        return maxLen
    }

OC

/*
 * 滑动窗口法
 */
 - (NSInteger)lengthOfLongestSubstring:(NSString *)s {
    if (s.length < 2) {
        return s.length;
    }
    
    NSInteger strLen = s.length;
    NSInteger maxLen = 0;
    NSInteger start = 0;
    NSMutableDictionary *map = [NSMutableDictionary dictionary];
    
    for (NSInteger i=0; i<strLen; i++) {
        unichar c = [s characterAtIndex:i];
        
        NSString *charStr = [NSString stringWithCharacters:&c length:1];
        NSNumber *idxNum = [map objectForKey:charStr];
        if (idxNum) {
            start = MAX(start, [idxNum integerValue] + 1);
        }
        
        map[charStr] = @(i);
        maxLen = MAX(maxLen, i-start+1);
    }
    
    return maxLen;
}

4.寻找两个正序数组的中位数

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。

Swift

class Solution {
    func findMedianSortedArrays(_ nums1: [Int], _ nums2: [Int]) -> Double {
        let totalLen = nums1.count + nums2.count;
        
        if totalLen % 2 == 0 {
            let sum = getKthElement(num1: nums1, num2: nums2, kth: (totalLen+1)/2) + getKthElement(num1: nums1, num2: nums2, kth: (totalLen+2)/2)
            return Double(sum) / 2.0
        }else {
            let res = getKthElement(num1: nums1, num2: nums2, kth: (totalLen+1)/2)
            return Double(res)
        }
    }
    
    
    /* 主要思路:要找到第 k (k>1) 小的元素,那么就取 pivot1 = nums1[k/2-1] 和 pivot2 = nums2[k/2-1] 进行比较
     * nums1 中小于等于 pivot1 的元素有 nums1[0 .. k/2-2] 共计 k/2-1 个
     * nums2 中小于等于 pivot2 的元素有 nums2[0 .. k/2-2] 共计 k/2-1 个
     * 取 pivot = min(pivot1, pivot2),两个数组中小于等于 pivot 的元素共计不会超过 (k/2-1) + (k/2-1) <= k-2 个
     * 这样 pivot 本身最大也只能是第 k-1 小的元素
     * 如果 pivot = pivot1,那么 nums1[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums1 数组
     * 如果 pivot = pivot2,那么 nums2[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums2 数组
     * 由于我们 "删除" 了一些元素(这些元素都比第 k 小的元素要小),因此需要修改 k 的值,减去删除的数的个数
     */
    func getKthElement(num1: [Int], num2:[Int], kth: Int) -> Int {
        let m: Int = num1.count
        let n: Int = num2.count
        var k = kth
        
        var index1: Int = 0, index2: Int = 0
        
        while true {
            
            //处理边界情况
            if index1 == m {
                return num2[index2 + k - 1]
            }
            
            if index2 == n {
                return num1[index1 + k - 1]
            }
            
            if k == 1 {
                return min(num1[index1], num2[index2])
            }
            
            //处理正常情况
            let newIdx1: Int = min(index1 + k/2 - 1, m-1)
            let newIdx2: Int = min(index2 + k/2 - 1, n-1)
            
            let pivot1 = num1[newIdx1]
            let pivot2 = num2[newIdx2]
            
            if pivot1 <= pivot2 {
                k -= newIdx1 - index1 + 1
                index1 = newIdx1 + 1
            }else {
                k -= newIdx2 - index2 + 1
                index2 = newIdx2 + 1
            }
        }
    }
}

OC

- (CGFloat)findMedianSortedArraysWithNums1:(NSArray *)num1 nums2: (NSArray *)num2 {
    
    NSInteger totalLength = num1.count + num2.count;
    if (totalLength % 2 != 0) {
        return [self getKthElement:num1 arr2:num2 kth:(totalLength+1)/2];
    }else {
        CGFloat result = ([self getKthElement:num1 arr2:num2 kth:(totalLength+1)/2] + [self getKthElement:num1 arr2:num2 kth:(totalLength+2)/2])/2.0;
        return result;
    }
}

/* 主要思路:要找到第 k (k>1) 小的元素,那么就取 pivot1 = nums1[k/2-1] 和 pivot2 = nums2[k/2-1] 进行比较
 * 这里的 "/" 表示整除
 * nums1 中小于等于 pivot1 的元素有 nums1[0 .. k/2-2] 共计 k/2-1 个
 * nums2 中小于等于 pivot2 的元素有 nums2[0 .. k/2-2] 共计 k/2-1 个
 * 取 pivot = min(pivot1, pivot2),两个数组中小于等于 pivot 的元素共计不会超过 (k/2-1) + (k/2-1) <= k-2 个
 * 这样 pivot 本身最大也只能是第 k-1 小的元素
 * 如果 pivot = pivot1,那么 nums1[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums1 数组
 * 如果 pivot = pivot2,那么 nums2[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums2 数组
 * 由于我们 "删除" 了一些元素(这些元素都比第 k 小的元素要小),因此需要修改 k 的值,减去删除的数的个数
 */
- (NSInteger)getKthElement:(NSArray <NSNumber *>*)num1 arr2:(NSArray <NSNumber *>*)num2 kth:(NSInteger)k {
    NSInteger m = num1.count;
    NSInteger n = num2.count;
    
    NSInteger index1 = 0, index2 = 0;
    
    while (true) {
        
        //处理边界情况
        if (index1 == m) {
            NSNumber *num = num2[index2 + k - 1];
            return [num integerValue];
        }
        
        if (index2 == n) {
            NSNumber *num = num1[index1 + k - 1];
            return [num integerValue];
        }
        
        if (k == 1) {
            return MIN([num1[index1] integerValue], [num2[index2] integerValue]);
        }
        
        
        //正常情况
        NSInteger newIndex1 = MIN(index1+k/2-1, m-1);
        NSInteger newIndex2 = MIN(index2+k/2-1, n-1);
        NSInteger pivot1 = [num1[newIndex1] integerValue];
        NSInteger pivot2 = [num2[newIndex2] integerValue];
        
        if (pivot1 <= pivot2) {
            k -= newIndex1 - index1 + 1;
            index1 = newIndex1 + 1;
        }else {
            k -= newIndex2 - index2 + 1;
            index2 = newIndex2 + 1;
        }
    }
}

5.最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

Swift

动态规划

class Solution {
    func longestPalindrome(_ s: String) -> String {
        let len: Int = s.count
        if len < 2 {
            return s
        }
        
        var begin: Int = 0
        var maxLen: Int = 1
        let charArr:[Character] = Array(s);
        
        var dp: [[Bool]] = [[Bool]](repeating: [Bool](repeating: false, count: len), count: len)
    
        for i in 0..<len {
            dp[i][i] = true
        }
        
        for L in 2...len {
            for i in 0...len {
                let j = L + i - 1
                if j >= len {
                    break
                }
                
                if charArr[i] != charArr[j] {
                    dp[i][j] = false
                }else {
                    if j - i < 3 {
                        dp[i][j] = true
                    }else {
                        dp[i][j] = dp[i+1][j-1]
                    }
                }
                
                if dp[i][j] && j-i+1 > maxLen {
                    maxLen = j-i+1;
                    begin = i;
                }
            }
        }
        
        
        let range = s.index(s.startIndex, offsetBy: begin)..<s.index(s.startIndex, offsetBy: begin+maxLen)
        return String(s[range])
    }
}

OC

动态规划

- (NSString *)longestPalindrome:(NSString *)s {
    NSInteger len = s.length;
    if (len < 2) {
        return s;
    }
    
    NSInteger maxLen = 1;
    NSInteger begin = 0;
    
    //将字符串转成字符数组
    NSMutableArray *charArr = [NSMutableArray array];
    for (NSInteger i=0; i<s.length; i++) {
        unichar character = [s characterAtIndex:i];
        [charArr addObject:[NSString stringWithFormat:@"%c", character]];
    }
    
    NSMutableArray *dp = [NSMutableArray arrayWithCapacity:len];
    for (NSInteger i=0; i<len; i++) {
        NSMutableArray *innerArr = [NSMutableArray arrayWithCapacity:len];
        for (NSInteger j=0; j<len; j++) {
            innerArr[j] = [NSNumber numberWithBool:NO];
        }
        dp[i] = innerArr;
    }
    
    for (NSInteger i=0; i<len; i++) {
        dp[i][i] = [NSNumber numberWithBool:YES];
    }
    
    for (NSInteger L = 2; L<=len; L++) {
        for (NSInteger i=0; i<len; i++) {
            //确定j的位置,根据j-i+1=L等式
            NSInteger j = L+i-1;
            
            // 如果右边界越界,就可以退出当前循环
            if (j>=len) {
                break;
            }
            
            if (![charArr[i] isEqualToString:charArr[j]]) {
                dp[i][j] = [NSNumber numberWithBool:NO];
            }else {
                if (j-i<3) {
                    dp[i][j] = [NSNumber numberWithBool:YES];
                }else {
                    dp[i][j] = dp[i+1][j-1];
                }
            }
            
            if ([dp[i][j] boolValue] && j-i+1>maxLen) {
                maxLen = j-i+1;
                begin = i;
            }
        }
    }
    
    return [s substringWithRange:NSMakeRange(begin, maxLen)];
}

6.N 字形变换

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:
P A H N
A P L S I I G
Y I R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);

Swift

利用二维矩阵模拟

//方法一 利用二维矩阵模拟
func convert(_ s: String, _ numRows: Int) -> String {
        //处理边界情况,若1 row or 1 column
        let n: Int = s.count
        if numRows == 1 || n <= numRows {
            return s
        }
        
        let t: Int = 2*numRows-2 //一个周期字符数
        let cpt: Int = numRows - 1 //一个周期所占列数
        let c: Int = (n+t-1)/t * cpt //总列数,注意最后一列填充满
        
        //构造 numrow行c列矩阵
        var datas: [[String]] = [[String]](repeating: [String](repeating: "", count: c), count: numRows);
        
        var x: Int = 0
        var y: Int = 0
        //遍历
        for i in 0..<n {
            let s: String = String(s[s.index(s.startIndex, offsetBy: i)])
            
            datas[x][y] = s
            
            if i % t < numRows - 1 {//向下遍历
                x += 1
            }else {//向斜上遍历
                x -= 1
                y += 1
            }
        }
        
        var result: String = ""
        for i in 0..<numRows {
            for j in 0..<c {
                let temps = datas[i][j]
                if temps.count > 0 {
                    result = result.appending(temps)
                }
            }
        }
        
        return result
    }

压缩矩阵

func convert(_ s: String, _ numRows: Int) -> String {
        //处理边界情况,若1 row or 1 column
        let n: Int = s.count
        if numRows == 1 || n <= numRows {
            return s
        }
        
        let t: Int = 2*numRows-2 //一个周期字符数
        
        //构造字符串数组
        var datas:[String] = [String](repeating: "", count: numRows);
        
        var x: Int = 0
        //遍历并填充值
        for i in 0..<n {
            let s: String = String(s[s.index(s.startIndex, offsetBy: i)])
            
            datas[x] = datas[x].appending(s)
            
            if i % t < numRows - 1 {//向下遍历
                x += 1
            }else {//向斜上遍历
                x -= 1
            }
        }
        
        var result: String = ""
        for i in 0..<numRows {
            result = result.appending(datas[i])
        }
        return result
    }

直接构造法

func convert(_ s: String, _ numRows: Int) -> String {
        //处理边界情况,若1 row or 1 column
        let n: Int = s.count
        if numRows == 1 || n <= numRows {
            return s
        }
        
        let t: Int = 2*numRows-2 //一个周期字符数
    
        var ans: String = ""
        
        for i in 0..<numRows {
            var j = 0
            while j + i < n {
                ans = ans.appending(String(s[s.index(s.startIndex, offsetBy: j+i)]))//第一个字符
                
                if i > 0 && i < numRows - 1 && j + t - i < n {
                    ans = ans.appending(String(s[s.index(s.startIndex, offsetBy: j+t-i)]))// 当前周期的第二个字符
                }
                
                j += t
            }
        }
        
        return ans
    }

K神flag解法(***** 推荐)

func convert(_ s: String, _ numRows: Int) -> String {
        if numRows < 2 {
            return s
        }
        
        var rows = Array(repeating: "", count: numRows)
        var i = 0, flag = -1
        
        for c in s {
            rows[i].append(c)
            if i == 0 || i == numRows - 1 {
                flag = -flag
            }
            i += flag
        }
        
        var res = ""
        for row in rows {
            res += row
        }
        return res
    }

OC

利用二维矩阵模拟

- (NSString *)convert:(NSString *)s numRows:(NSInteger)numRows {
    if (!s) {
        return nil;
    }
    
    NSInteger len = s.length;
    //处理边界情况,若1 row or 1 column
    if (numRows == 1 || len <= numRows) {
        return s;
    }
    
    
    NSInteger t = 2*numRows - 2;//周期
    NSInteger np = numRows - 1;//1个周期占用的矩阵列数
    NSInteger c = ceil(len+t-1/t) * np;//总列数
    
    //构造r行c列的矩阵
    NSMutableArray <NSMutableArray *>*rows = [NSMutableArray arrayWithCapacity:numRows];
    for (NSInteger i=0; i<numRows; i++) {
        NSMutableArray <NSString *>*tempArr = [NSMutableArray arrayWithCapacity:c];
        for (NSInteger j=0; j<c; j++) {
            tempArr[j] = @"";
        }
        rows[i] = tempArr;
    }
    
    NSInteger x = 0;
    NSInteger y = 0;
    
    //遍历字符串
    for (NSInteger i=0; i<len; i++) {
        unichar unichar = [s characterAtIndex:i];
        NSString *res = [[NSString alloc] initWithCharacters:&unichar length:1];
        
        rows[x][y] = res;
        if (i % t < numRows-1) {//向下填充
            ++x;
        }else {//向斜上填充
            --x;
            ++y;
        }
    }
    
    NSString *result = @"";
    for (NSInteger i=0; i<numRows; i++) {
        for (NSInteger j=0; j<c; j++) {
            NSString *val = rows[i][j];
            if (val.length > 0) {
                result = [result stringByAppendingString:val];
            }
        }
    }
    
    return result;
}

flag解法

//K神flag解法(*****推荐 )
/*
 通过标志位,控制索引在numRows层来回扫描,思路清晰简洁
 */
- (NSString *)convert:(NSString *)s numRows:(NSInteger)numRows {
    if (numRows < 2) {
        return s;
    }
    
    NSInteger len = s.length;
    
    //构造存储字符串的数组
    NSMutableArray <NSString *>*datas = [NSMutableArray array];
    for (NSInteger i=0; i<numRows; i++) {
        datas[i] = @"";
    }
    
    NSInteger idx = 0, flag = -1;
    
    for (NSInteger i=0; i<len; i++) {
        unichar unichar = [s characterAtIndex:i];
        NSString *res = [[NSString alloc] initWithCharacters:&unichar length:1];
        
        datas[idx] = [datas[idx] stringByAppendingString:res];
        
        if (idx == 0 || idx == numRows-1) {
            flag = - flag;
        }
        idx += flag;
    }
    
    NSString *result = @"";
    for (NSString *str in datas) {
        result = [result stringByAppendingString:str];
    }
    
    return result;
}

7. 整数反转

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [−231,
231 − 1] ,就返回 0。 假设环境不允许存储 64 位整数(有符号或无符号)。

Swift

func reverse(_ x: Int) -> Int {
        var x = x;
        var n: Int = 0
        
        while x != 0 {
            n = n * 10 + x % 10
            x /= 10
        }
        
        if n < Int32.min || n > Int32.max {
            return 0
        }else {
            return n
        }
    }

OC

-(int)reverse:(int)x {
    int n = 0;
    
    while (x) {
        n = n * 10 + x % 10;
        x /= 10;
    }
    
    if (n > INT32_MAX || n < INT32_MIN) {
        return 0;
    }else {
        return n;
    }
}

8. 字符串转换整数 (atoi)

Swift

有限状态机

func myAtoi(_ s: String) -> Int {
        let auto = AutomationSwift()
        for chara in s {
            auto.getChar(chara: chara)
        }
        
        return Int(auto.flag) * auto.num
    }
    
    
    
    enum StateEnum : Int {
        case start;
        case signed;
        case inNumber;
        case end;
    }

    class AutomationSwift: NSObject {
        public var flag: Int32 = 1
        public var num: Int = 0
        
        var state: StateEnum = .start
        
        let transitionTable:[StateEnum : Array<StateEnum>]
        
        override init() {
            self.transitionTable = [
                .start:     [.start, .signed, .inNumber, .end],
                .signed :   [.end, .end, .inNumber, .end],
                .inNumber:  [.end,.end, .inNumber, .end],
                .end:       [.end, .end, .end, .end,],
            ];
        }
        
        public func getChar(chara: Character) -> Void {
            let idx: Int = getCharIdx(chara: chara).rawValue
            let newState = self.transitionTable[state]![idx]
            
            self.state = newState
            
            if state == .inNumber {
                num = num * 10 + Int(chara.asciiValue! - Character("0").asciiValue!)
                num = flag == 1 ? min(num, Int(INT32_MAX)) : min(num, -Int(Int32.min))
            }else if state == .signed {
                flag = chara == "+" ? 1 : -1
            }
        }
        
        func getCharIdx(chara: Character) -> StateEnum {
            if chara == " " {
                return .start
            }
            
            if chara == "+" || chara == "-" {
                return .signed
            }
            
            if chara >= "0" && chara <= "9" {
                return .inNumber
            }
            
            return .end
        }
    }

OC

有限状态机

- (int)myAtoi:(NSString *)s {
    Automation *autom = [[Automation alloc] init];
    
    for (NSInteger i=0; i<s.length; i++) {
        unichar unichar = [s characterAtIndex:i];
        
        [autom getChar:unichar];
    }
    int res = autom.flagV * autom.num;
    return res;
}

@implementation Automation {
    NSDictionary <NSNumber *, NSArray *>*_transitionTable;
    
    StateEnum _state;
}

- (instancetype)init {
    if (self = [super init]) {
        
        _flagV = 1;
        _num = 0;
        _state = StateEnumStart;
        
        _transitionTable = @{
           @(StateEnumStart) : @[@(StateEnumStart), @(StateEnumSigned), @(StateEnumInNumber), @(StateEnumEnd)],
           @(StateEnumSigned) : @[@(StateEnumEnd), @(StateEnumEnd), @(StateEnumInNumber), @(StateEnumEnd)],
           @(StateEnumInNumber) : @[@(StateEnumEnd), @(StateEnumEnd), @(StateEnumInNumber), @(StateEnumEnd)],
           @(StateEnumEnd) : @[@(StateEnumEnd), @(StateEnumEnd), @(StateEnumEnd), @(StateEnumEnd)],
        };
        
        return self;
    }
    
    return nil;
}

- (void)getChar:(unichar)character {
    
    NSInteger idx = [self getIndexOfCharacter:character];
    NSArray *states = [_transitionTable objectForKey:@((NSInteger)_state)];
    _state = (StateEnum)[states[idx] integerValue];
    
    if (_state == StateEnumInNumber) {
        _num = _num * 10 + character - '0';
        _num = self.flagV == 1 ? MIN(_num, INT32_MAX) : MIN(_num, INT32_MAX);
    }else if(_state == StateEnumSigned) {
        if (character == '+') {
            self.flagV = 1;
        }else if(character == '-') {
            self.flagV = - 1;
        }
    }
}

- (NSInteger)getIndexOfCharacter:(unichar)character {
    if (character == ' ') {
        return 0;
    }
    
    if (character == '+' || character == '-') {
        return 1;
    }
    
    if (character >= '0' && character <= '9') {
        return 2;
    }
    
    return 3;
}

9. 回文数

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

Swift

func isPalindrome(_ x: Int) -> Bool {
        
        //处理边界情况
        //负数or最后一位是0
        if x < 0 || (x % 10 == 0 && x/10 != 0) {
            return false
        }
        
        //如果是回文数,反转后的部分和未翻转的应该相等,因此翻转数字的一半,节省时间及空间
        var reverSuffix:Int = 0
        //翻转
        var x = x
        while (x > reverSuffix){
            reverSuffix = reverSuffix * 10 + x%10;
            x /= 10
        }
        
        //当数字为奇数个时,通过reverSuffix/10去除末尾
        if x == reverSuffix || x == reverSuffix/10 {
            return true
        }
        
        return false
    }

OC

- (BOOL)isPalindrome:(NSInteger)x {
    //处理边界情况
    if (x < 0 || (x%10 == 0 && x/10 != 0)) {
        return NO;
    }
    
    //翻转一半后判断是否相等即可确定是否为回文数
    NSInteger reversedNum = 0;
    while (x > reversedNum) {
        reversedNum = reversedNum * 10 + x%10;
        x /= 10;
    }
    
    //奇数时多一位,因此除以10
    if (x == reversedNum || x == reversedNum/10) {
        return YES;
    }
    return NO;
}

10. 正则表达式匹配

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘’ 的正则表达式匹配。
‘.’ 匹配任意单个字符
'
’ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

Swift

动态规划

func isMatch(_ s: String, _ p: String) -> Bool {
        let m = s.count
        let n = p.count
        
        let matches = { (i:Int, j:Int) ->Bool  in
            if i == 0 {
                return false
            }
            
            if p[p.index(p.startIndex, offsetBy: j-1)] == "." {
                return true
            }
            
            return s[s.index(s.startIndex, offsetBy: i-1)] == p[p.index(p.startIndex, offsetBy: j-1)]
        }
        
        var f:[[Int]] = [[Int]](repeating: [Int](repeating: 0, count: n+1), count: m+1)
        f[0][0] = 1
        for i in 0...m {
            for j in 1...n {
                if p[p.index(p.startIndex, offsetBy: j-1)] == "*" {
                    f[i][j] |= f[i][j-2]
                    
                    if matches(i, j-1) {
                        f[i][j] |= f[i-1][j]
                    }
                }else {
                    if matches(i, j) {
                        f[i][j] |= f[i-1][j-1]
                    }
                }
            }
        }
        
        return (f[m][n] != 0)
    }

OC

动态规划

- (BOOL)matchStr:(NSString *)s pStr:(NSString *)p {
    NSInteger m = s.length;
    NSInteger n = p.length;
    
    BOOL (^matches)(NSInteger, NSInteger) = ^BOOL(NSInteger i, NSInteger j) {
        if (i == 0) {
            return NO;
        }
        
        if ([p characterAtIndex:j-1] == '.') {
            return YES;
        }
        
        return [s characterAtIndex:i-1] == [p characterAtIndex:j-1];
    };
    
    //构造状态转移表
    NSMutableArray *f = [[NSMutableArray alloc] initWithCapacity:m+1];
    for (NSInteger i=0; i<m+1; i++) {
        NSMutableArray *subArr = [[NSMutableArray alloc] initWithCapacity:n+1];
        for (NSInteger j=0; j<n+1; j++) {
            subArr[j] = @(0);
        }
        f[i] = subArr;
    }
    
    f[0][0] = @(1);
    
    for (NSInteger i=0; i<=m; i++) {
        for (NSInteger j=1; j<=n; j++) {
            if ([p characterAtIndex:j-1] == '*') {
                f[i][j] = @([f[i][j] intValue] | [f[i][j-2] intValue]);
                
                if (matches(i, j-1)) {
                    f[i][j] = @([f[i][j] intValue] | [f[i-1][j] intValue]);
                }
            }else {
                if (matches(i, j)) {
                    f[i][j] = @([f[i][j] intValue] | [f[i-1][j-1] intValue]);
                }
            }
        }
    }
    
    return [f[m][n] boolValue];
    
    return false;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jarlen John

谢谢你给我一杯咖啡的温暖

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值