《剑指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 ...
随机推荐
- E.Magic Master(The 2019 Asia Nanchang First Round Online Programming Contest)
直接模拟orhttps://blog.csdn.net/liufengwei1/article/details/100643831
- Elastic Search中mapping的问题
Mapping在ES中是非常重要的一个概念.决定了一个index中的field使用什么数据格式存储,使用什么分词器解析,是否有子字段,是否需要copy to其他字段等.Mapping决定了index中 ...
- C++入门基础知识(二)
一:引用 概念:是给一个已经存在的变量取一个别名,编译器不会为引用变量开辟内存空间,它和引用的变量公用一块内存空间. 例如: 类型& 引用变量名(对象名)= 引用实体 int& a = ...
- Specialization For SCCM
JUST A LINK FOR ALL SCCM QUESTION http://eskonr.com/
- C#中判断文件夹或文件是否存在的方法
一.根据虚拟路径获取文件物理路径: string savePath = Server.MapPath("~/Uploads/RemoteDatum/"); 二.判断文件夹是否存在 ...
- Winform_chart控件_心得
效果图: 1.首先,在工具箱找到chart控件,拖到窗体中. 2.关于chart控件的细节设计: series集合设计: chartType可以选择折线图.柱状图.圆饼图等等. isValueShow ...
- [转载]为什么用Java开发桌面程序的比较少
这个是本人这几天用javafx开发桌面程序时候想到的,因为虽然javafx比C#之类的确实坑多不少,但是习惯了之后也还行,而且它的一次编译.各处使用真的深得我心.但为什么不流行呢: 作者:bell 来 ...
- vue学习(5)-评论功能(利用父组件的方法)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- vue编程式导航,命名路由
//使用 window.location.href 的形式,叫做 编程式导航 绑定事件的形式 <template> <div class="goods-item" ...
- SQL 多表查询展示
########################多表########################SELECT COUNT(*) FROM MEMBER1 A; 查询出来的结果为43行数据: SEL ...