《剑指offer》算法题第十一天
今日题目:
- 滑动窗口的最大值
- 扑克牌中的顺子
- 圆圈中最后剩下的数字
- 求1+2+3+...+n
- 不用加减乘除做加法
- 构建乘积数组
今天的题目比较有意思,可以学到很多知识,包括第1题中的数据结构——双向队列,第3题约瑟夫环问题等。
1.滑动窗口的最大值
题目描述:
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{,,,,,,,}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{,,,,,}; 针对数组{,,,,,,,}的滑动窗口有以下6个: {[,,],,,,,}, {,[,,],,,,}, {,,[,,],,,}, {,,,[,,],,}, {,,,,[,,],}, {,,,,,[,,]}。 思路:
比较直接的方法是维护一个窗口,然后对于每个窗口找出当前窗口的最大值。这种方法的时间复杂度为O(kn)其中k为窗口大小。
另外一种方法是,利用队列,在队列中放置有可能为最大值的对象,将当前的最大值放在队首,这样就可以在O(1)的时间内得到最大值,这需要用到双向队列。
代码如下:
/**
用一个双端队列,队列第一个位置保存当前窗口的最大值,当窗口滑动一次
1.判断当前最大值是否过期
2.新增加的值从队尾开始比较,把所有比他小的值丢掉
*/
import java.util.ArrayDeque;
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
ArrayList<Integer> res = new ArrayList();
if(size == 0) return res; ArrayDeque<Integer> queue = new ArrayDeque();
int begin = 0;
for(int i = 0; i < num.length; i++){
begin = i - size + 1;
if(queue.isEmpty())
queue.add(i);
else if(begin > queue.peekFirst())
queue.pollFirst(); while(!queue.isEmpty() && num[queue.peekLast()] <= num[i])
queue.pollLast();
queue.add(i); if(begin >= 0)
res.add(num[queue.peekFirst()]);
}
return res; }
}
2. 扑克牌中的顺子
题目描述:
从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为0,可以看成任意数字。 思路:
比较直接,由于0可以代替任何数字,我们先把数组排序一下,然后计算0的个数,最后判断0的个数是否大于不连续的数字间隔数。
代码如下:
import java.util.*;
public class Solution {
public boolean isContinuous(int [] nums) {
if(nums.length == 0)
return false;
Arrays.sort(nums);
int count_zero = 0;
int count_no_con = 0;
for(int i = 0; i < nums.length-1; i++){
if(nums[i] == 0)
count_zero++;
else if(nums[i+1]==nums[i])
return false;
else{
if(nums[i+1]-nums[i] > 1){
count_no_con += (nums[i+1]-nums[i]-1);
}
}
}
return count_zero >= count_no_con;
}
}
3.圆圈中最后剩下的数字
题目描述:
0,1,2,...,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。 思路:
这是有名的约瑟夫环问题,《剑指》中给出了两种解题方法:一种是用环形链表模拟圆圈;另一种是分析每次被删除的数字的规律并直接计算出圆圈中最后剩下的数字。
下面只贴出第二种算法,它是基于递归实现的,推导出递归方程的过程比较复杂,这边就不作阐述,感兴趣的朋友可参考:https://www.nowcoder.net/questionTerminal/f78a359491e64a50bce2d89cff857eb6
代码如下:
public class Solution {
public int LastRemaining_Solution(int n, int m) {
if(n == 0) return -1;
if(n == 1) return 0;
return (LastRemaining_Solution(n-1,m)+m)%n;
}
}
4. 求1+2+3+...+n
题目描述:
求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。 思路:
1. 运用数学公式 (1+n)*n/2
2. 递归,递归出口利用且(&&)运算的短路特性。
代码如下:
//利用且(&&)运算的短路特性
public class Solution {
public int Sum_Solution(int n) {
int sum = n;
boolean ans = (n > 0) && (sum += Sum_Solution(n-1))>0;
return sum;
}
}
5. 不用加减乘除做加法
题目描述:
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。 思路:
利用位运算来模拟加法运算,先做不进位的加法(异或),再算出进位(与,左移一位),然后再做和与进位的加法。其实这是一个递归的思想。
代码如下:
public class Solution {
public int Add(int num1,int num2) {
int sum = 0;
int carry = 0;
do{
sum = (num1 ^ num2);
carry = (num1 & num2) << 1;
num1 = sum;
num2 = carry;
}while(carry != 0);
return num1;
}
}
6. 构建乘积数组
题目描述:
给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。 思路:
一种比较直接的思路是用double loop来构建乘积数组,简单,但是时间复杂度为O(n2)。
另一种解决方法是将A[0]*A[1]*...*A[i-1]以及A[i+1]*...*A[n-1]分别存起来,最后再进行整合。
代码如下:
import java.util.ArrayList;
public class Solution {
public int[] multiply(int[] A) {
int n = A.length;
int[] left = new int[n];
int[] right = new int[n];
left[0] = 1;
for(int i = 1; i < n; i++){
left[i] = left[i-1]*A[i-1];
}
right[n-1] = 1;
for(int i = n-2; i >= 0; i--){
right[i] = right[i+1]*A[i+1];
}
int[] B = new int[n];
for(int i = 0; i < n; i++){
B[i] = 1;
B[i] = left[i]*right[i];
}
return B;
}
}
《剑指offer》算法题第十一天的更多相关文章
- 《剑指Offer》题五十一~题六十
五十一.数组中的逆序对 题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数.例如,在数组{7, 5, 6, 4}中,一共存 ...
- 《剑指Offer》题四十一~题五十
四十一.数据流中的中位数 题目:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中 ...
- 《剑指Offer》题三十一~题四十
三十一.栈的压入.弹出序列 题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的数字均不相等.例如,序列{1, 2, 3, 4 ,5}是某栈的压栈序列 ...
- 《剑指Offer》题二十一~题三十
二十一.调整数组顺序使奇数位于偶数前面 题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分. 测试用例: 功能测试:输入数组中的奇 ...
- 《剑指Offer》题六十一~题六十八
六十一.扑克牌中的顺子 题目:从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的.2~10为数字本身,A为1,J为11,Q为12,K为13,而大.小王可以看成任意数字. 六十二.圆圈中 ...
- 剑指offer算法题
数组中只出现一次的数字(一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字): 解法在于位运算中的异或,直接异或可以得到这两个数的异或,按照最后的有效数字位可以 ...
- 剑指offer算法总结
剑指offer算法学习总结 节选剑指offer比较经典和巧妙的一些题目,以便复习使用.一部分题目给出了完整代码,一部分题目比较简单直接给出思路.但是不保证我说的思路都是正确的,个人对算法也不是特别在行 ...
- 剑指Offer——算法复杂度中的O(logN)底数是多少
剑指Offer--算法复杂度中的O(logN)底数是多少 前言 无论是计算机算法概论.还是数据结构书中,关于算法的时间复杂度很多都用包含O(logN)这样的描述,但是却没有明确说logN的底数究竟是多 ...
- 剑指 offer 第一题: 二维数组中的查找
打算写 图解剑指 offer 66 题 的系列文章,不知道大家有没有兴趣
- 剑指Offer编程题2——替换空格
剑指Offer编程题2——替换空格 题目描述 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happ ...
随机推荐
- Thrift Oneway是什么?
网上很多文章,都有各种涉及使用 oneway 的,基本是一个THRIFT IDL示例接口前面加 oneway.看完之后对 oneway的理解还是很模糊,于是看了下Thrift的代码,终于搞懂了 one ...
- linux lkm rootkit常用技巧
简介 搜集一下linux lkm rootkit中常用的一些技巧 1.劫持系统调用 遍历地址空间 根据系统调用中的一些导出函数,比如sys_close的地址来寻找 unsigned long ** g ...
- ubuntu切换root用户
方法一:sudo su命令 方法二:sudo -i 方法三:su root
- Java 线程控制
一.线程控制 和线程相关的操作都定义在Thread类中,但在运行时可以获得线程执行环境的信息.比如查看可用的处理器数目(这也行?): public class RunTimeTest { public ...
- codeforce C. Success Rate
写完这道题目才发现自己对二分的理解太浅了 这题是典型的利用二分“假定一个问题可行并求最优解” 二分是通过不断缩小区间来缩小解的范围,最终得出解的算法 我们定义一个c(x) 表示判断函数 如果对任意y& ...
- asp.net 8 Request,Response,Server
Request成员: 1.Request.UrlReferrer 获取请求的来源,可以防盗链 Response.Write(Request.Url.ToString());//获取当前请求的URL地址 ...
- 解决EntityFramework与System.ComponentModel.DataAnnotations命名冲突
比如,定义entity时指定一个外键, [ForeignKey("CustomerID")] public Customer Customer { get; set; } 编译时报 ...
- O048、掌握 cinder-scheduler 调度逻辑
参考https://www.cnblogs.com/CloudMan6/p/5589707.html 上一节我们详细讨论了cinder-api 和 cinder-volume ,今天讨论另一个重要 ...
- 初识python之了解程序设计基本方法
对于用计算机解决一些问题,这里有一个程序设计的基本方法,主要分为六个步骤,其分析和实现过程如下: (1)分析问题:利用计算机解决问题需要结合计算机技术的发展水平和人类对问题的思考程度,在特定技术和社会 ...
- 5、SVN 权限管理
5.SVN 权限管理 5.1版本库中三个对应的配置文件 版本库配置文件目录 /var/svn/repository/pro_oa/conf svnserve.conf 文件,如下修改: 19# ano ...