leetcode 167周赛题解

二进制链表转整数

代码:

class Solution {
public:
    int getDecimalValue(ListNode* head) {
         int ans =0 ;
         while(head!=NULL){
            ans = ans * 2 + head->val;
            head = head->next;
         }
         return ans;
    }
};
class Solution:
    def getDecimalValue(self, head):
        ans = 0
        while head !=None:
            ans = ans* 2 + head.val
            head = head.next
        return ans

顺次数

代码:

class Solution {
public:
    vector<int> sequentialDigits(int low, int high) {
        vector<int>ans;
        for(int len=1;len<10;len++){
           for(int start = 1;start<11- len;start++){
             int tmp = 0;
             for(int i=start;i<start+len;i++){
                tmp = tmp*10 + i;
             }
             if(tmp>=low&&tmp<=high) ans.push_back(tmp);
           }
        }
        return ans;
    }
};
class Solution:
    def sequentialDigits(self, low, high):
        ans = []
        for len in range(1,10):
            for start in range(1,10-len+1):
                tmp = 0
                for num in range(start, min(10,start + len)):
                    tmp = tmp *10 + num
                if tmp>= low and tmp <=high:
                     ans.append(tmp)
        return ans

元素和小于等于阈值的正方形的最大边长

题意:

在一个mxn矩阵里找到一个边长最长的正方形之和小于一个阈值。

思路:

首先,对矩阵预处理一下(容斥原理)实现 O(1) 求正方形之和 ,然后偷懒写法可以O(n)枚举边长,但O(n*m*min(n,m))的复杂度python版本过不了,但c++能过(),所以更优的做法是二分边长,时间复杂度就变成O(n*m*log(min(n,m)))

看来leetcode 用 python 做题要更细致的考虑时间复杂度…

代码:

c++ 版 O(n*m*min(n,m))复杂度 332 ms

class Solution {
private:
    int a[305][305];
    long long s[305][305];
public:
    int maxSideLength(vector<vector<int>>& mat, int threshold) {
        int n = mat.size();
        int m = mat[0].size();
        memset(s, 0, sizeof s);
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= m; ++j) {
                a[i][j] = mat[i - 1][j - 1];
                s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
            }
        int ans = 0;
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= m; ++j) {
                for (int k = 1; k <= i && k <= j; ++k) 
                    if (s[i][j] - s[i - k][j] - s[i][j - k] + s[i - k][j - k] <= threshold)
                        ans = max(ans, k);
            }
        return ans;
    }
};

C++ 版 O(n*m*log(min(n,m)))复杂度 108 ms

class Solution {
private:
    int a[305][305];
    long long s[305][305];
public:
    int maxSideLength(vector<vector<int>>& mat, int threshold) {
        int n = mat.size();
        int m = mat[0].size();
        memset(s, 0, sizeof s);
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= m; ++j) {
                a[i][j] = mat[i - 1][j - 1];
                s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
            }
        int ans = 0;
        int l =0, r =min(n,m);
        while(l<=r){
            int k = (l+r)/2;
            int ok = 0;
            for (int i = k; i <= n; ++i){
                for (int j = k; j <= m; ++j) {
                        if (s[i][j] - s[i - k][j] - s[i][j - k] + s[i - k][j - k] <= threshold){
                            ans = max(ans, k);
                            ok = 1;
                        }
                }
            }
            if(ok==1) l = k +1;
            else r = k -1;
        }
        return ans;
    }
};

Python版 O(n*m*log(min(n,m)))复杂度 1404 ms

class Solution:
    def maxSideLength(self, mat, threshold) :
        n, m = len(mat) , len(mat[0])
        #print('n:', n , 'm:', m)
        sum = [ [0] * (m+1) for i in range(n+1)]
        a  =  [ [0] * (m+1) for i in range(n+1)]
        for i in range(1,n+1):
            for j in range(1,m+1):
               a[i][j] = mat[i-1][j-1]
               sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + a[i][j]
        ans = 0
        l = 0 ; r = min(n,m);
        while l <=r :
            d = int((l+r)/2)
            flag = False
            for i in range(d,n+1):
                for j in range(d,m+1):
                    # for d in range(1,min(i+1 ,j+1)): # python如果不二分就会超时
                        num =  sum[i][j] - sum[i-d][j] - sum[i][j-d] + sum[i-d][j-d]
                        if num <= threshold:
                            ans = max(ans, d)
                            flag = True
            if flag:
                l = d +1
            else :
                r = d -1
        return ans

网格中的最短路径

题意:

有障碍的迷宫,给k次机会破除障碍的机会,问最少步数从(0,0)出发走到(n-1,m-1)。

思路:

多用一个状态记录当前破除过几次障碍的的广搜(dfs),实际上由于广搜的特点,第一次到达出口的步数就是最后的答案。

这里有个插曲,数据的问题从(0,0)到(n-1,m-1),广搜的四个方向的顺序会影响程序的效率(最优先向下右),因为这个问题,python版本我TLE了一发。

代码:


class Solution {
public:
    struct node{
       int x,y,k;
       node(){}
       node(int _x, int _y, int _k) {x = _x; y = _y; k = _k;}
    };

    int shortestPath(vector<vector<int>>& grid, int k) {
       queue<node>q;
       int n = grid.size(),m = grid[0].size();
       int step[n+10][m+10][k+10];
       memset(step,-1,sizeof(step));
       if(grid[0][0] == 1){
           q.push(node(0,0,1));
       }
       else{
           q.push(node(0,0,0));
       }
       step[0][0][0] = 0;
       while(!q.empty()){
         node now = q.front(); q.pop();
         if(now.x == n-1 && now.y ==m-1){
             return step[now.x][now.y][now.k];
         }
         int nxt[4][2] = {{0,1},{1,0},{-1,0},{0,-1}};
         for(int i=0;i<4;i++){
            int nx = now.x + nxt[i][0];
            int ny = now.y + nxt[i][1];
            if(nx>=0&&nx<n&&ny>=0&&ny<m){
                int nk = now.k + grid[nx][ny];
                if(nk<=k&&step[nx][ny][nk]==-1){
                    step[nx][ny][nk] = step[now.x][now.y][now.k] + 1;
                    //cout<<nx<<" "<<ny<<" "<<nk<<" "<<step[nx][ny][nk]<<endl;
                    q.push(node(nx,ny,nk));
                }
            }
         }
       }
       return -1;
    }
};

class Solution:
    def shortestPath(self, grid, k) :
        t = 0
        vis = set()
        n, m = len(grid),len(grid[0])
        if grid[0][0] == 1:
            q = [(0,0,0,1)]
            vis.add((0,0,1))
        else :
            q = [(0,0,0,0)]
            vis.add((0,0,0))
        while t< len(q):
            now = q[t]
            t+=1
            if now[0] == n - 1 and now[1] == m - 1: return now[2]
            for step in [[0,1],[1,0],[-1,0],[0,-1]]:
                nx = now[0] + step[0]
                ny = now[1] + step[1]
                #print(nx,ny)
                if 0 <= nx < n and 0 <= ny< m:
                    nk = now[3] + grid[nx][ny]
                    if nk <= k:
                        if (nx, ny, nk) not in vis:
                            #print(nx,ny,nk)
                            vis.add((nx, ny, nk))
                            q.append((nx, ny, now[2] + 1, nk))
        return -1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值