• 剑指Offer面试题解总结61~70


    剑指Offer61~70

    和为s的两个数字

    题链
    题解:双指针问题,设两个指针l,r分别指向数组首尾,然后每次判断nums[l]+nums[r]是否大于target,如果大于则r–,r遍历完后l++.

     public int[] twoSum(int[] nums, int target) {
          int l = 0,r = nums.length-1;
          while(l < r){
             
              while(nums[l] + nums[r] > target){
                  r--;
              }
               if(nums[l] + nums[r] ==  target){
                  return new int[]{nums[l],nums[r]};
              }
              l++;
          }
          return new int[2];
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    和为s的连续正数序列

    题链
    题解:双指针问题.设两个指针l,r每次记录sum=(l+r)(r-l+1)/2与target的大小,当sum==target则返回l~r,sum< target则r++,否则l++.

     public int[][] findContinuousSequence(int target) {
           List<int[]> list = new ArrayList<>();
            for(int l = 1,r = 2; l < r;){
                int sum = (l + r) * (r - l + 1) / 2;
                if(sum == target){
                    int[] cur = new int[r - l + 1];
                    for(int i = l;i <= r; i++){
                        cur[i-l] = i;
                    }
                    list.add(cur);
                    l++;
                }else if(sum < target){
                    r++;
                }else{
                    l++;
                }
            }
            return list.toArray(new int[list.size()][]);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    翻转单词顺序

    题链
    题解:首先去掉原字符串的前后的多余空格,然后分别翻转每个单词,然后再翻转整个字符串.

    public String reverseWords(String s) {
        if(s == null || s.length() == 0){
            return s;
        }
          String[] strs = s.split(" ");
            String ans = "";
            int n = strs.length;
            for(int i = n-1; i >= 0; i--){
                if("".equals(strs[i])){
                    continue;
                }
                ans += strs[i] + " ";
            }
            if(ans.length() == 0){
                return ans;
            }
            return ans.substring(0,ans.length()-1);
        }
        public char[] reverse(char[] arr,int l,int r){
            while(l < r){
                char tmp = arr[l];
                arr[l] = arr[r];
                arr[r] = tmp;
                l++;
                r--;
            }
            return arr;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    左旋转字符串

    题链
    题解:与翻转字符串思路类似,以第k个字符作为分割分别翻转左侧和右侧的子字符串后再翻转整个字符串.还有一种骚操作:将两个字符串拼接起来,然后返回新字符串的第k位到第k+length位.

     public String reverseLeftWords(String s, int n) {
            String ans = s + s;
            int len = s.length();
            return ans.substring(n,n+len);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    滑动窗口的最大值

    题链
    题解:考察的是单调队列的应用.维护一个单调队列:队首为最大值.每次更新新元素时要保证队列的递减.同时在移除头部元素时要检验队首元素的下标是否应该被移除.

     public int[] maxSlidingWindow(int[] nums, int k) {
            Deque<Integer> q = new LinkedList<>();
            int n = nums.length;
            if(n == 0){
                return nums;
            }
            int[] ans = new int[n - k + 1];
            int index = 0;
            for(int i = 0; i < n; i++){
                while(!q.isEmpty() && nums[i] >= nums[q.peekLast()]){
                    q.pollLast();
                }
                q.offerLast(i);
                if(i >= k - 1){
                    ans[index++] = nums[q.peekFirst()];
                    if(q.peekFirst() == i - k + 1){
                        q.pollFirst();
                    }
                }
            }
            return ans;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    队列的最大值

    题链
    题解:维护两个队列,一个队列负责元素的进和出,一个队列负责表示当前队列中的最大元素.分别记为q和maxQ,在进元素时,q中直接进元素,maxQ进行一次判断:当maxQ为空或maxQ的队头元素小于等于进入元素时将元素放入队列中,否则先弹出maxQ的队头元素.在出元素时,q中直接出元素,maxQ中要判断出的元素是否等于maxQ的队头元素,如果等于将maxQ的队头元素也弹出.

     Deque<Integer> q;
        Deque<Integer> maxQ;
        public MaxQueue() {
            q = new LinkedList<>();
            maxQ = new LinkedList<>();
        }
    
        public int max_value() {
            if(q.size() == 0){
                return -1;
            }
            return maxQ.peekFirst();
        }
    
        public void push_back(int value) {
            q.offerLast(value);
            while(!maxQ.isEmpty() && value > maxQ.peekLast()){
                maxQ.pollLast();
            }
            maxQ.offerLast(value);
        }
    
        public int pop_front() {
            if(q.size() == 0){
                return -1;
            }
            if(maxQ.peekFirst().equals(q.peekFirst())){
                maxQ.pollFirst();
            }
            return q.pollFirst();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    n个骰子的点数

    题链
    题解:动态规划.记录f[i][j]为i个骰子向上和为j时的概率.那么f[i][j] = (f[i-1][j-1]+…+f[i-1][j-6])/6.

      public double[] dicesProbability(int n) {
            double[] dp = new double[6];
            Arrays.fill(dp,1.0/6);
            for(int i = 2; i <= n; i++){
                double[] cur = new double[5*i+1];
                for(int j = 0; j < dp.length; j++){
    				//之所以正着推是为了避免多次讨论数组越界
                    for(int k = 0; k < 6; k++){
                        cur[j+k] += dp[j] / 6.0;
                    }
                }
                dp = cur;
            }
              return dp;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    扑克牌中的顺子

    题链
    题解:简单的模拟题.首先对数组排序,当数组中出现两个相同非0的数字时返回false.记录0出现的次数cnt和数组中非零的最大差sum-1-(3-cnt,比较两者的值,当前者大于等于后者时返回true.

     public boolean isStraight(int[] nums) {
            Arrays.sort(nums);
            for(int i = 0; i < 4; i++){
                if(nums[i] == nums[i+1] && nums[i] != 0){
                    return false;
                }
            }
            if(isV(nums)){
                return true;
            }
            int cnt = 0;
            for(int i = 0; i < 5; i++){
                if(nums[i] == 0){
                    cnt++;
                }
            }
            int sum = 0;
            sum = nums[4] - nums[cnt] -1-(3-cnt);
            return sum <= cnt;
    
        }
        public boolean isV(int[] nums){
            return (nums[0] + 1 == nums[1] && nums[1] + 1 == nums[2]
                && nums[2] + 1 == nums[3] && nums[3] + 1 == nums[4]);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    圆圈中最后剩下的数字

    题链
    题解:约瑟夫环.对于n个元素,第一个要删除的数是第m%n个,假设n-1个元素最终剩下的元素的编号是x,那么f[n] = (m%n+x) % n,因此可以通过迭代得到最终结果.

    	 public int lastRemaining(int n, int m) {
    		int a = 0;
    		for(int i = 2; i <= n; i++){
    			a = (m+a)%i;
    		}
    		return a;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    股票的最大利润

    题链
    题解:利用贪心去解决.首先定义一个当前天的最小价格minPrice和当前天得到的最大利润maxProfit.顺序遍历数组的每个元素,每次比较minPrice与当前元素的值,如果前者大于后者则用后者更细前者,否则判断当前天数-minPrince与maxProfit的大小,如果前者更大,则用前者更新后者.

     public int maxProfit(int[] prices) {
            int price = Integer.MAX_VALUE;
            int profit = 0;
            int len = prices.length;
            for(int i = 0; i < len; i++){
                if(prices[i] < price){
                    price = prices[i];
                }else if(prices[i] - price > profit){
                    profit = prices[i] - price;
                }
            }
            return profit;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    [oeasy]python0019_ 打包和解包_struct_pack_unpack
    Event Loop——事件循环
    算力基础设施的现状、趋势和对策建议
    ES6对象字面量的新功能
    到底要不要写注释?
    YOLOV8的tensorrt部署详解(目标检测模型-CUDA)
    springboot读取配置文件自定义参数和自定义配置文件参数
    漫画 | 单元测试实在是太可怕了!
    赛宁网安荣获国贸集团2022网络安全演练活动“优秀保障奖”
    涂鸦智能携手亚马逊云科技 共建“联合安全实验室” 为IoT发展护航
  • 原文地址:https://blog.csdn.net/weixin_52477733/article/details/126374934