面试经典150题【131-140】

文章目录

  • 面试经典150题【131-140】
    • 123.买卖股票的最佳时机III
    • 188.买卖股票的最佳时机IV
    • 二分查找的板子:
    • 35.搜索插入位置
    • 74.搜索二维矩阵
    • 162.寻找峰值
    • 33.搜索旋转排序数组
    • 34.在排序数组中查找元素的第一个和最后一个位置
    • 153.寻找旋转排序数组中的最小值
    • 4.寻找两个正序数组的中位数

面试经典150题【131-140】

123.买卖股票的最佳时机III

在这里插入图片描述
buy1代表第一次买,sell1代表第一次卖。
buy2代表第二次买,sell2代表第二次卖。
每个值的最大值/迭代值,都与上一个商业操作有关。
同一天买入卖出不影响,因为利润为0

class Solution {
    public int maxProfit(int[] prices) {
        int buy1=-prices[0],sell1=0;
        int buy2=-prices[0],sell2=0;
        for(int i=0;i<prices.length;i++){
            buy1=Math.max(buy1,-prices[i]);
            sell1=Math.max(sell1,buy1+prices[i]);
            buy2=Math.max(buy2,sell1-prices[i]);
            sell2=Math.max(sell2,buy2+prices[i]);
        }
        return sell2;
    }
}

188.买卖股票的最佳时机IV

在这里插入图片描述

class Solution {
    public int maxProfit(int k, int[] prices) {
        if (prices.length == 0) {
            return 0;
        }

        int n = prices.length;
        //k = Math.min(k, n / 2);
        int[] buy = new int[k];
        int[] sell = new int[k];
        Arrays.fill(buy,-prices[0]);
        Arrays.fill(sell,0);
       
        for (int i = 0; i < n; ++i) {
            buy[0]=Math.max(buy[0],-prices[i]);
            sell[0]=Math.max(sell[0],buy[0]+prices[i]);
            for (int j = 1; j < k; ++j) {
                buy[j] = Math.max(buy[j], sell[j-1] - prices[i]);
                sell[j] = Math.max(sell[j], buy[j] + prices[i]);
            }
        }

        return Arrays.stream(sell).max().getAsInt();
    }
}

无需考虑同一天的买卖和k值与n/2的问题,直接模版梭哈。
在一轮i的循环中,对无数个buy和sell赋值即可
注意要对buy和sell初始化。

二分查找的板子:

小于等于的

class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0, right = nums.length - 1; // 注意
        while(left <= right) { // 注意
            int mid = (left + right) / 2; // 注意
            if(nums[mid] == target) { // 注意
                // 相关逻辑
            } else if(nums[mid] < target) {
                left = mid + 1; // 注意
            } else {
                right = mid - 1; // 注意
            }
        }
        // 相关返回值
        return ?;
    }
}

小于的

class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0, right = nums.length; // 注意
        while(left < right) { // 注意
            int mid = (left + right) / 2; // 注意
            if(nums[mid] == target) {
                // 相关逻辑
            } else if(nums[mid] < target) {
                left = mid + 1; // 注意
            } else {
                right = mid; // 注意
            }
        }
        // 相关返回值
        return ?;
    }
}

然后我们看一下Java内置的Arrays.binarySearch的方法:

    private static int binarySearch0(int[] a, int fromIndex, int toIndex,
                                     int key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            int midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }

我们可以发现他就是用的小于等于的模版,只不过最后的return的时候有些特别。

35.搜索插入位置

在这里插入图片描述

class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] == target)
                return mid;
            if (nums[mid] > target)
                right = mid - 1;
            if (nums[mid] < target)
                left = mid + 1;
        }
        return left;

    }
}

74.搜索二维矩阵

在这里插入图片描述
在这里插入图片描述
先往下搜索找到具体的行,再往右搜索找具体的值。
但是这个题咔咔错
在这里插入图片描述
首先用找到target左边的元素的方法,然后再用标准二分查找有没有这个元素即可。

class Solution {
    public  boolean searchMatrix(int[][] matrix, int target) {
        int len1 = matrix.length, len2 = matrix[0].length;
        int index = binarySearchFirstColumn(matrix,target);
        if(index<0) return false;
        if (matrix[index][0] == target)
            return true;
        int[] matrixRow = new int[len2];
        for (int i = 0; i < len2; i++) {
            matrixRow[i] = matrix[index][i];
        }
        int ans = Arrays.binarySearch(matrixRow, target);
        if (ans < 0)
            return false;
        else
            return true;
    }

    public int binarySearchFirstColumn(int[][] matrix, int target) {
        int low = 0, high = matrix.length - 1;
        while (low <= high) {
            int mid = (high - low ) / 2 + low;
            if(matrix[mid][0]==target) return mid;
            if (matrix[mid][0] < target) {
                low = mid+1 ;
            } else {
                high = mid - 1;
            }
        }

        return high<0? 0:high;
    }


}

尤其是这个找第一列,最后的return很特别。是判断high是否小于0
这种是寻找小于等于目标值的最右边的索引。return high<0? 0:high

162.寻找峰值

在这里插入图片描述

class Solution {
    public int findPeakElement(int[] nums) {
        int left = 0, right = nums.length - 1;
        for (; left < right; ) {
            int mid = left + (right - left) / 2;
            if (nums[mid] > nums[mid + 1]) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left;

    }
}

对于1,4,5,6,2,7,8,9,10来说,
只要数组中存在一个元素比相邻元素大,那么沿着它一定可以找到一个峰值。2<7.则最后答案是10.

33.搜索旋转排序数组

nums是升序的。
在这里插入图片描述

class Solution {
    public int search(int[] nums, int target) {
        int left = 0, right = nums.length - 1, mid = 0;
        while (left <= right) {
            mid = (left + right) / 2;
            if (target == nums[mid])
                return mid;
            // mid在左区间里
            if (nums[mid] >= nums[left]) {

                if (target >= nums[left] && target < nums[mid]) {
                    // target在mid的左边
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }

            } else {
                if (target > nums[mid] && target <= nums[right]) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
        }
        return -1;

    }
}

旋转以后,肯定是4567123,nums[0]一定比后面的右段大
先判断nums[mid]和nums[0]的关系,判断是在左段(数值比较大的一段)还是右段(数值比较小的一段)
然后比较target和nums[mid]的关系,判断他在mid的左边还是右边。

34.在排序数组中查找元素的第一个和最后一个位置

在这里插入图片描述

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        int first = -1;
        int last = -1;
        // 找第一个等于target的位置
        while (left <= right) {
            int middle = (left + right) / 2;
            if (nums[middle] == target) {
                first = middle;
                right = middle - 1; // 重点
            } else if (nums[middle] > target) {
                right = middle - 1;
            } else {
                left = middle + 1;
            }
        }
        // 最后一个等于target的位置
        left = 0;
        right = nums.length - 1;
        while (left <= right) {
            int middle = (left + right) / 2;
            if (nums[middle] == target) {
                last = middle;
                left = middle + 1; // 重点
            } else if (nums[middle] > target) {
                right = middle - 1;
            } else {
                left = middle + 1;
            }
        }
        return new int[] { first, last };
    }
}

以找最左边的first为例,即使找到了,也要再做一次right = mid-1;继续遍历。直到不等于(即越界)

153.寻找旋转排序数组中的最小值

在这里插入图片描述
一定要理解旋转数组是一个数字大的前半段和一个数字小的后半段。
如果nums[mid]>nums[right] ,说明mid在左半段,则left=mid+1
右边不能-1,万一右半段只有一个数字。
当然如果nums[left]<nums[mid],这说明nums[left]就是最小值了。

class Solution {
    public int findMin(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] > nums[right]) {          
                left = mid + 1;
            } else {                                
                right = mid;
            }
        }
        return nums[left];


    }
}

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

在这里插入图片描述
当 [ [a1],[b1,b2,b3] | [a2,…an],[b4,…bn] ]

我们只需要比较 b3 和 a2 的关系的大小,就可以知道这种分法是不是准确的!

例如:我们令:

nums1 = [-1,1,3,5,7,9]

nums2 = [2,4,6,8,10,12,14,16]

当 m1 = 4,m2 = 3 ,它的中位数就是median = (num1[m1] + num2[m2])/2

时间复杂度:O(log(min(m,n)))

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int n1 = nums1.length;
        int n2 = nums2.length;
        if (n1>n2)
            return findMedianSortedArrays(nums2, nums1);
        //对于6+8而言,k=7 0-7和8-15. 对于6+7而言,K还是7,0-6,7,8-14
        int k = (n1 + n2 + 1)/2;
        int left = 0;
        //这个right也设置的很巧妙。
        int right = n1;
        //这里的left和right都是对于短的nums1而言的。
        while(left < right){
            int m1 = left +(right - left)/2;
            int m2 = k - m1;
            if (nums1[m1] < nums2[m2-1])
                left = m1 + 1;
            else
                right = m1;
        }
        //这样对于7+7的来说,m1=7,m2=0
        //对于 6+7而言,K=7,m1=6,m2=1
        int m1=left,m2=k-left;
        int c1 = Math.max(m1 <= 0 ? Integer.MIN_VALUE : nums1[m1-1],
                         m2 <= 0 ? Integer.MIN_VALUE : nums2[m2-1]);
        if ((n1 + n2) % 2 == 1)
            return c1;
        int c2 = Math.min( m1 >= n1 ? Integer.MAX_VALUE :nums1[m1],
                         m2 >= n2 ? Integer.MAX_VALUE : nums2[m2]);
        return (c1 + c2) * 0.5;

    }
}

感觉二分这边就很恶心。上一道题就需要设置right=n1才行。然而大部分题是设置right=n1-1;
需要控制好很多边界变量的设置,即使会了板子也不一定能搞出来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/513945.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

练习 18 Web [RoarCTF 2019]Easy Calc

表达式注入&#xff0c;被屏蔽字符的处理方式 一开始先看一下前端的源码 有一个calc.php&#xff0c;肯定需要打开 这是calc中的代码 <?php error_reporting(0); if(!isset($_GET[num])){show_source(__FILE__); }else{$str $_GET[num];$blacklist [ , \t, \r, \n,\,…

计算机网络-HTTP相关知识-HTTP的发展

HTTP/1.1 特点&#xff1a; 简单&#xff1a;HTTP/1.1的报文格式包括头部和主体&#xff0c;头部信息是键值对的形式&#xff0c;使得其易于理解和使用。灵活和易于扩展&#xff1a;HTTP/1.1的请求方法、URL、状态码、头字段等都可以自定义和扩展&#xff0c;使得其具有很高的…

【Android、 kotlin】kotlin学习笔记

基本语法 fun main(){val a2var b "Hello"println("$ (a - 1} $b Kotlin!")} Variables 只赋值一次用val read-only variables with val 赋值多次用var mutable variables with var Standard output printin() and print() functions String templ…

蓝桥杯第793题——排水系统

题目描述 对于一个城市来说&#xff0c;排水系统是极其重要的一个部分。 有一天&#xff0c;小 C 拿到了某座城市排水系统的设计图。排水系统由 n 个排水结点&#xff08;它们从 1∼n 编号&#xff09;和若干个单向排水管道构成。每一个排水结点有若干个管道用于汇集其他排水…

分布式链路追踪与云原生可观测性

分布式链路追踪系统历史 Dapper, a Large-Scale Distributed Systems Tracing Infrastructure - Google Dapper&#xff0c;大规模分布式系统的跟踪系统大规模分布式系统的跟踪系统&#xff1a;Dapper设计给我们的启示 阿里巴巴鹰眼技术解密 - 周小帆京东云分布式链路追踪在金…

Node.js环境调用百度智能云(百度云)api鉴权认证三步走

方式一 :Postman脚本的方式生成v1版本的认证字符串 Postman脚本下载 下载Postman pre-request Script 设置 Authorization 示例脚本 方式二&#xff1a;在线签名工具生成 (试用于验证编程字符串签名是否有错误) 签名计算工具 https://cloud.baidu.com/signature/index.html …

Acrel-1000DP光伏监控系统在尚雷仕(湖北)健康科技有限公司5.98MW分布式光伏10KV并网系统的应用

摘 要&#xff1a;分布式光伏发电特指在用户场地附近建设&#xff0c;运行方式多为自发自用&#xff0c;余电上网&#xff0c;部分项目采用全额上网模式。分布式光伏全额上网的优点是可以充分利用分布式光伏发电系统的发电量&#xff0c;提高分布式光伏发电系统的利用率。发展分…

C++ //练习 11.3 编写你自己的单词计数程序。

C Primer&#xff08;第5版&#xff09; 练习 11.3 练习 11.3 编写你自己的单词计数程序。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /*************************************************************************> …

拾光坞N3 ARM 虚拟主机 i茅台项目

拾光坞N3 在Dcoker部署i茅台案例 OS&#xff1a;Ubuntu 22.04.1 LTS aarch64 cpu&#xff1a;RK3566 ram&#xff1a;2G 部署流程——》mysql——》java8——》redis——》nginx mysql # 依赖 apt update apt install -y net-tools apt install -y libaio* # 下载mysql wg…

JavaBean是什么?

Bean的本意为豌豆、子实&#xff0c;在这里引申为一种实体。JavaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean&#xff0c;类必须是具体的和公共的&#xff0c;并且具有无参数的构造器。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性&#xff0…

鸿蒙南向开发实战:【智能窗帘】

样例简介 智能窗帘设备不仅接收数字管家应用下发的指令来控制窗帘开启的时间&#xff0c;而且还可以加入到数字管家的日程管理中。通过日程可以设定窗帘开关的时间段&#xff0c;使其在特定的时间段内&#xff0c;窗帘自动打开或者关闭&#xff1b;通过日程管家还可以实现窗帘…

基础篇3 浅试Python爬虫爬取视频,m3u8标准的切片视频

浅试Python爬取视频 1.页面分析 使用虾米视频在线解析使用方式&#xff1a;https://jx.xmflv.cc/?url目标网站视频链接例如某艺的视频 原视频链接 解析结果: 1.1 F12查看页面结构 我们发现页面内容中什么都没有&#xff0c;video标签中的src路径也不是视频的数据。 1.2 …

VUE运行项目后,只有local地址,没有network地址(添加nerwork地址)

使用前 使用后 解决方案 1.找到build文件夹下的webpack.dev.conf.js文件&#xff0c;更改messages中的内容 devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({compilationSuccessInfo: {messages: [App running: ,Local: http://${devWebpackConfig.devServer.hos…

【前端Vue】社交信息头条项目完整笔记第3篇:三、个人中心,TabBar 处理【附代码文档】

社交媒体-信息头条项目完整开发笔记完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;一、项目初始化使用 Vue CLI 创建项目,加入 Git 版本管理,调整初始目录结构,导入图标素材,引入 Vant 组件库,移动端 REM 适配。二、登录注册准备,实现基本登录功能,登录状…

ObjectiveC-08-OOP面向对象程序设计-类的分离与组合

本节用一简短的文章来说下是ObjectiveC中的类。类其实是OOP中的一个概念&#xff0c;概念上简单来讲类是它是一组关系密切属性的集合&#xff0c;所谓的关系就是对现实事物的抽象。 上面提到的关系包括很多种&#xff0c;比如has a&#xff0c; is a&#xff0c;has some等&…

交互设计师、UI设计师、视觉设计师面试作品集包装模板figma源文件

页面数量&#xff1a;19页 页面尺寸&#xff1a;1920*1080PX 交付格式&#xff1a;figma 赠送文件&#xff1a;24款高质量样机 交付文件&#xff1a;作品集模板源文件、作品集包装psd源文件、作品集所用字体文件 该作品集虽然只有19页&#xff0c;但可根据需求复制作品集里已有…

offsetof宏定义的使用和模拟实现详解

目录 一.offsetof宏定义的使用二.offsetof宏的模拟实现三.总结 一.offsetof宏定义的使用 offsetof的第一个参数是数据类型(结构体或联合体)&#xff0c;第二个参数是偏移量 &#xff08;offsetof用于计算结构体和联合体的偏移量&#xff09; 返回值的类型是size_t&#xff08;无…

Spring Cloud微服务入门(二)

微服务的技术栈 服务治理&#xff1a; 服务注册、发现、调用。 负载均衡&#xff1a; 高可用、集群部署。 容错&#xff1a; 避免雪崩、削峰、服务降级。 消息总线&#xff1a; 消息队列、异步通信&#xff0c;数据一致性。 网关&#xff1a; 校验路径、请求转发、服务集成…

Golang 开发实战day07 - Functions

Golang 教程07 - Functions 1. Functions 1.1 什么是函数&#xff1f; 在 Golang 中&#xff0c;函数就像是代码的超级组合体&#xff0c;可以将一段代码封装成一个独立的单元&#xff0c;以便重复使用。 1.2 函数声明 func funcName(parameter1 type1, parameter2 type2)…

利用sqoop实现sql表数据导入到Hadoop

1.在开发这创建好sql表后&#xff0c;开始执行下面步骤 2.sqoop的安装路径&#xff0c;我这里放在以下位置 3. 进入到option2脚本中&#xff0c;下面是脚本里的内容 下面四点要根据情况随时更改&#xff1a; 1>jdbc:mysql://node00:3306/数据库名 2>sid,sname->前…