【Notes13】剑指offer_11-20题


11.旋转数组的最小数字

在这里插入图片描述

//java版
class Solution {
    
    
	public int minArray(int[] nums) {
    
    
		int n = nums.length - 1;
		if(n < 0) return -1;
		while(n > 0 && nums[n] == nums[0]) n --;
		if(nums[n] >= nums[0]) return nums[0];
		int l = 0, r = n;
		while(l < r)
		{
    
    
			int mid = l + r >> 1; //[l, mid]  [mid + 1, r]
			if(nums[mid] < nums[0]) r = mid;
			else l = mid + 1;
		}
		return nums[l];
	}
}
//C++版
class Solution {
    
    
public:
    int minNumberInRotateArray(vector<int> nums) {
    
    
        int n = nums.size() - 1;
        if(n < 0) return 0;
        
        while(nums[n] == nums[0] && n > 0) n --;
        if(nums[n] >= nums[0]) return nums[0];
        
        int l = 0, r = n;
        while(l < r)
        {
    
    
            int mid = l + r >> 1; //[l, mid] [mid+1, r]
            if(nums[mid] < nums[0]) r = mid;
            else l = mid + 1;
        }
        return nums[r];
    }
};

12.矩阵中的路径

在这里插入图片描述

//java版
class Solution {
    
    
	//回溯法 dfs
	public boolean exist(char[][] board, String word) {
    
    
		for(int i = 0; i < board.length; i ++)
			for(int j = 0; j < board[0].length; j ++)
				if(dfs(board, word, 0, i, j))
					return true;
		return false;
	}
	private boolean dfs(char[][] board, String word, int u, int x, int y)
	{
    
    
		//先判断边界 后比较相等
		if(x >= board.length || x < 0 || y >= board[0].length || y < 0 || board[x][y] != word.charAt(u))
			return false;
		if(u == word.length() - 1) return true;
		char temp = board[x][y];
		board[x][y] = '*';
		//递归遍历
		boolean res = dfs(board, word, u + 1, x - 1, y) || dfs(board, word, u + 1, x + 1, y) || dfs(board, word, u + 1,x, y - 1) || dfs(board, word, u + 1, x, y + 1);
		board[x][y] = temp;
		return res;
	}
}
//C++版
class Solution {
    
    
public:
    bool hasPath(char* matrix, int rows, int cols, char* str)
    {
    
    
        if(rows == 1 && cols == 1)
            if(matrix[0] == str[0]) return true;
            else return false;
        
        //matrix  
        //str str  \0
        for(int i = 0; i < rows; i ++)
            for(int j = 0; j < cols; j ++)
                if(dfs(matrix, rows, cols, str, 0, i, j))
                    return true;
        
        return false;
    }
    
    bool dfs(char* matrix, int rows, int cols, char* str, int u, int x, int y)
    {
    
    
        if(str[u] == '\0') return true;
        
        int dx[4] = {
    
    -1, 0, 1,0}, dy[4] = {
    
    0, 1, 0, -1};
        for(int i = 0; i < 4; i ++)
        {
    
    
            int a = x + dx[i], b = y + dy[i];
            if(a >= 0 && a < rows && b >= 0 && b < cols && matrix[a * cols + b] == str[u])
            {
    
    
                char t = matrix[a * cols + b];
                matrix[a * cols + b] = '*';
                if(dfs(matrix, rows, cols, str, u + 1, a, b))
                    return true;
                matrix[a * cols + b] = t;
            }
        }
        return false;
    }


};

13.机器人的运动范围

在这里插入图片描述

//java版
class Solution {
    
    
    int m, n, k;
    boolean[][] visited;
    public int movingCount(int m1, int n1, int k1) {
    
    
        //找规律
        //19 20   小8
        //39 40   小8
        //x9 x+1 0 小8
        //普通情况 12  13  +1
        m = m1;
        n = n1;
        k = k1;
        visited = new boolean[m][n];//false
        return dfs(0, 0, 0, 0);
    }
    private int dfs(int x, int y, int sx, int sy)
    {
    
    
        //sx sy对应 x y数位之和
        // x 16 y 20 sx 7 sy 2
        //边界优先 m- 1 n -1
        if(x >= m || y >= n || k < sx + sy || visited[x][y]) return 0;
        visited[x][y] = true;
        //sx + sy <= k
        return 1 +  dfs(x + 1, y, (x + 1) % 10 != 0   sx + 1 : sx - 8 , sy) 
                + dfs(x, y + 1, sx, (y + 1) % 10 != 0   sy + 1 : sy - 8);
    }
}
//C++版
class Solution {
    
    
public:
    
    int get_sum(pair<int, int> p)
    {
    
    
        int s = 0;
        while(p.first)
        {
    
    
            s += p.first % 10;
            p.first /= 10; 
        }
        while(p.second)
        {
    
    
            s += p.second % 10;
            p.second /= 10; 
        }
        
        return s;
    }
    
    int movingCount(int threshold, int rows, int cols)
    {
    
    
        int res = 0;
        
        if(!cols || !rows) return 0;
        
        queue<pair<int, int>> q;
        vector<vector<bool>> st(rows, vector<bool>(cols, false));
        
        //bfs
        int dx[4] = {
    
    -1, 0, 1, 0}, dy[4] = {
    
    0, 1, 0, -1};
        q.push({
    
    0, 0});
        //bfs
        while(q.size())
        {
    
    
            pair<int, int> t = q.front();
            q.pop();
            
            if(st[t.first][t.second] || get_sum(t) > threshold) continue;
            
            res ++;
            st[t.first][t.second] = true;
            
            for(int i = 0; i < 4; i ++)
            {
    
    
                int x = t.first + dx[i], y = t.second + dy[i];
                if(x >= 0 && x< rows && y >= 0 && y < cols) q.push({
    
    x, y});
            }
        }
        
        return res;
    }
};

14.剪绳子

在这里插入图片描述

//java版
class Solution {
    
    
    public int cuttingRope(int n) {
    
    
        if (n < 2) {
    
    
            return 0;
        }
        int[] dp = new int[n + 1];
        dp[2] = 1;
        for (int i = 3; i <= n; i++) {
    
    
            for (int j = 1; j < i; j++) {
    
    
                dp[i] = Math.max(Math.max(j * dp[i - j], j * (i - j)), dp[i]);
            }
        }
        return dp[n];
    }
}
//C++版
class Solution {
    
    
public:
    int cutRope(int n) {
    
    
        //数学
        //子绳子
        // >=5
        //ni     3 * (ni - 3) = 3*ni - 9 >  ni;    2*ni > 9
        // == 4 
        // 2  2   1  3
        // 3 > 1 *2
        // 2 > 1*1
        /*
        if(n <= 3) return n - 1;
        
        int res = 1;
        if(n % 3 == 1) res *= 4, n -= 4;
        else if(n % 3 == 2) res *= 2, n -= 2;
        while(n)
        {
            res *= 3;
            n -= 3;
        }
        return res;
        */
        
        //动态规划
        if(n <= 3) return n - 1;
        
        int dp[n];
        dp[1] = 1;
        dp[2] = 2;
        dp[3] = 3;
        int res = 0;//记录最大的乘积
        for(int i = 4; i <= n ; i ++)
        {
    
    
            for(int j = 1; j <= i/2; j ++)
                res = max(res, dp[j] * dp[i - j]);
            dp[i] = res;
        }        
        return dp[n];
    }
};

15.二进制中1的个数

在这里插入图片描述

//java版
public class Solution {
    
    
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
    
    
        //n & (n - 1)
        //每执行一次 最右边的1变成0
        //unsigned int 
        int count = 0;
        while(n != 0)
        {
    
    
            count ++;
            n = n & (n - 1);
        }
        return count;
    }
}
//C++版
class Solution {
    
    
public:
     int  NumberOf1(int n) {
    
    
         
         int count = 0;
         while(n)
         {
    
    
             count ++;
             n = n & (n - 1);
         }
         return count;
     }
};

16.数值的整数次方

在这里插入图片描述

//java版
class Solution {
    
    
    public double myPow(double x, int n) {
    
    
        //快速幂
        //n用二进制表示
        if(x == 0) return 0;
        long b = n;// 2147483648,2147483647
        double res = 1.0;
        if(b < 0)
        {
    
    
            b = -b;//用long防止溢出
            x = 1 / x;
        }
        //快速幂
        while(b > 0)
        {
    
    
            if((b & 1) == 1) res *= x;//累乘
            x *= x; //2的次方
            b >>= 1;
        }
        return res;
    }
}
//C++版
class Solution {
    
    
public:
    double Power(double base, int e) {
    
    
        double res = 1;
        for(int i = 0; i < abs(e); i ++) res *= base;
        if(e < 0) res = 1 / res;
        return res;
    }
};

17.打印从1到最大的n位数

在这里插入图片描述

//java版
class Solution {
    
    
    public int[] printNumbers(int n) {
    
    
        if(n <= 0) return new int[0];
        int result = 1;
        int x = 10;
        //该题考查快速幂;
        while(n != 0){
    
    
            if((n & 1) == 1){
    
    
                result *= x;
            }
            n >>= 1;
            x *= x;
        }
        int len = result - 1;
        int[]array = new int[len];
        for(int i = 0;i < len;i++){
    
    
            array[i] = i + 1;
        }
        return array;
    }
}
//C++版
class Solution {
    
    
public:
    vector<int> printNumbers(int n) {
    
    
        char *number = new char[n+1];
        vector<int> ans;
        memset(number,'0',n);
        number[n] = '\0';
        while(!checkNumber(number,n)){
    
    
            ans.push_back(changeNumber(number,n));
        }
        return ans;
    }
    int changeNumber(char *number,int n){
    
    
        int res = 0;
        for(int i = 0;i < n;++i){
    
    
            res = res*10 + number[i]-'0';
        }
        return res;
    }
    bool checkNumber(char *number,int n){
    
    
        int nLength = n;
        bool isOverFlow = 0;
        int isTakeOver=1;
        for(int i = nLength - 1;i >= 0;--i){
    
    
            number[i] = number[i] + isTakeOver;
            if(number[i] > '9'){
    
    
                if(i == 0) {
    
    
                    isOverFlow = 1;
                    break;
                }
                number[i] = '0';
                isTakeOver = 1;
            }else{
    
    
                isTakeOver = 0;
            }
        }
        return isOverFlow;
    }
};

18.删除链表的节点

在这里插入图片描述

//java版
class Solution {
    
    
    public ListNode deleteNode(ListNode head, int val) {
    
    
        //前一个结点 指向 当前结点的下一个
        //则当前结点被删除
        //删除第一个结点 单独讨论
        //if(head.val == val) return head.next;
        ListNode dummy = new ListNode(0);//虚拟头结点
        dummy.next = head;
        ListNode pre = dummy;
        ListNode cur = dummy.next;
        //找到val结点
        while(cur.val != val && cur != null)
        {
    
    
            pre = cur;
            cur = cur.next;
        }
        //找到val 或者走到头了
        if(cur != null)
        {
    
    
            pre.next = cur.next;
        }
        return dummy.next;
    }
}
//C++版
class Solution {
    
    
public:
    ListNode* deleteDuplication(ListNode* head)
    {
    
    
        auto dummy = new ListNode(-1);
        dummy -> next = head;
        
        auto p = dummy;
        while(p -> next)
        {
    
    
            auto q = p -> next;
            while(q && p -> next -> val == q -> val) q = q -> next;
            
            if(p -> next -> next == q) p = p -> next;
            else p -> next = q;
        }
        
        return dummy -> next;
    }
};

19.正则表达式匹配

在这里插入图片描述

//java版
class Solution {
    
    
    public boolean isMatch(String s, String p) {
    
    
        //dp思路
        //f[i][j]  s的前i个字符  和 p 的前j个字符 匹配
        int n = s.length();
        int m = p.length();
        boolean[][] f = new boolean[n + 1][m + 1];
        for(int i = 0; i <= n; i ++)
            for(int j = 0; j <= m ; j ++)
            {
    
    
                if(j == 0) // i == j == 0
                    f[i][j] = (i == 0);
                else
                {
    
    
                    //* 
                    if(p.charAt(j - 1) != '*'){
    
    
                        //没有碰到*
                        if(i > 0 && (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '.'))
                            f[i][j] = f[i - 1][j - 1];
                    }else{
    
    
                        //碰到*
                        //* = 0
                        if(j >= 2)
                            f[i][j] |= f[i][j - 2];
                        //* != 0
                        if(i >= 1 && j >= 2 && (s.charAt(i - 1) == p.charAt(j - 2) || p.charAt(j - 2) == '.'))
                            f[i][j] |= f[i - 1][j];
                    }
                }
            }
        
        return f[n][m];
    }
}
//C++版
class Solution {
    
    
public:
    bool match(char* str, char* patten)
    {
    
    
        //两者都为空 true
        if(*str == '\0' && *patten == '\0')
            return true;
        //str不空 patten空
        if(*str != '\0' && *patten == '\0')
            return false;
        //str空 patten不空
        //         a* *:0
        //*:0...
        
        if(*(patten + 1) != '*')//匹配当前字符
        {
    
    
            if(*str == *patten || (*str != '\0' && *patten =='.'))   //str : any   patten :.
                return match(str + 1, patten + 1);
            else 
                return false;
        }
        else//patten +1 == * 
        {
    
    
            if(*str == *patten || (*str != '\0' && *patten =='.'))
                return match(str, patten + 2) || match(str + 1, patten);
                        // aa   a*aa
                        //aaa  .*a
            else//aa   c*aa
                return match(str, patten + 2);
        }
        
    }
};

20.表示数值的字符串

在这里插入图片描述

//java版
class Solution {
    
    
    public boolean isNumber(String s) {
    
    
        if(s == null || s.length() == 0)
            return false;
        
        boolean num = false;
        boolean dot = false;
        boolean e = false;
        char[] str = s.trim().toCharArray();//trim必须要 去掉两边空格
        for(int i = 0; i < str.length; i ++)
        {
    
    
            if(str[i] >= '0' && str[i] <= '9')
                num = true;
            else if(str[i] == '.')
            {
    
    
                // .之前 不能有. e
                if(dot || e)
                    return false;
                
                dot = true;
            }
            else if(str[i] == 'e' || str[i] == 'E')
            {
    
    
                // e 之前不能有e  必须有数字  1234e10
                if(e || !num)
                    return false;
                e = true;
                //12e 12e+
                num = false;
            }
            else if(str[i] == '+' || str[i] == '-')
            {
    
    
                //+-  第一个位置  或者 e后面的第一个位置
                if(i != 0 && str[i - 1] != 'e' && str[i - 1] != 'E')
                    return false;
            }
            else//出现其他特殊字符 buvjyvj
            {
    
    
                return false;
            }
        }
        return num;
    }
}
//C++版
class Solution {
    
    
public:
    bool isNumeric(char* string)
    {
    
    
        /*思路
        1. 连续..  no
        2.  e. no
        3. 连续 ee  EE   no
        4. e '\0'  no
        */
        if(string == NULL)
            return false;
        if(*string == '-' || *string == '+')
        {
    
    
            string ++;
            if(*string == '-' || *string == '+')
                return false; //+-15
        }
        //+-
        if(*string == '\0')
            return false;
        
        int dot = 0, e = 0, num = 0;
        while(*string  != '\0')
        {
    
    
            if(*string >= '0' && *string <= '9')
            {
    
    
                string ++;
                num ++;
            }
            else if(*string == '.')
            {
    
    
                //..  10e3.4
                if(dot > 0 || e > 0)
                    return false;
                string ++;
                dot ++;
            }
            //E
            else if(*string == 'e' || *string == 'E')
            {
    
    
                // e10  10e10e
                if(num == 0 || e > 0)
                    return false;
                string ++;
                e ++;
                if(*string == '-' || *string == '+')
                {
    
    
                    string ++;//10e-10
                    //10e--10
                    if(*string == '-' || *string == '+')
                        return false;
                }
                if(*string == '\0')//10e
                    return false;
            }
            else //as10
                return false;
        }
        return true;
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_43435675/article/details/107239766