算法编程-不定时更新
前言:这些算法题来源包括但不限于牛客,领扣,面试题等,有些有大佬的解答(看了感觉自己弱爆了),有些只有自己的,自己做的附有自己的解题思路,大佬的当然也有大佬的思路。
一、
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,
每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
思路:
1 2 6 9
2 6 8 10
6 9 13 15
10 13 45 46
x=8
由于每行数据是递增的,如x=8,那么 x 可能在第一行1<8<9,也可能在第二行2<8<10,同理也可能在第三行,不会在第四行
然后在可能的行中遍历,即可知道x是否在数组中.
解答:
public boolean Find(int target, int [][] array) {
if(array[0].length==0)
return false;
int leng = array.length;
int cleng=array[0].length;
int rnum=leng,cnum=cleng;
for(int i=0;i<leng;i++){
if(array[i][0]<=target&&array[i][cleng-1]>=target) {
for (int j=0;j<cleng;j++) {
if(target==array[i][j]){
return true;
}
}
}
}
return false;
}
二、
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.
则经过替换之后的字符串为We%20Are%20Happy。
思路:
StringBuffer 没有replaceAll()方法,所以用 StringBuffer.toString()方法转为String类型,若String转StringBuffer则通过构造方法,方法:
String s="这是一个字符串";
StringBuffer sb = new StringBuffer(s);
解答:
public String replaceSpace(StringBuffer str) {
return str.toString().replaceAll(" ","%20");
}
三、
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
思路:
1.冒泡排序
2.应该用三次翻转也行吧(暂时没空写代码,匿)
解答:
public int minNumberInRotateArray(int [] array) {
if(array.length==0)
return 0;
int temp;
int leng=array.length;
for(int i=0;i<leng;i++){
for(int j=i+1;j<leng;j++){
if(array[j]<array[i]){
temp = array[i];
array[i]=array[j];
array[j]=temp;
}
}
}
return array[0];
}
四、
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。
n<=39
斐波那契数列: 1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)
思路:
递归方法
解答:
public static int f(int x){
if(x<=1)
return x;
return f(x-1)+f(x-2);
}
五、
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
思路:
比较倾向于找规律的解法,f(1) = 1, f(2) = 2, f(3) = 3, f(4) = 5, 可以总结出f(n) = f(n-1) + f(n-2)的规律,但是为什么会出现这样的规律呢?假设现在6个台阶,我们可以从第5跳一步到6,
这样的话有多少种方案跳到5就有多少种方案跳到6,另外我们也可以从4跳两步跳到6,跳到4有多少种方案的话,就有多少种方案跳到6,其他的不能从3跳到6什么的啦,
所以最后就是f(6) = f(5) + f(4);这样子也很好理解变态跳台阶的问题了。
解答:
public static int JumpFloor(int target) {
if(target<3)
return target;
/*使用递归算法
return JumpFloor(target-1)+JumpFloor(target-2);*/
/*使用迭代*/
int first=1,second=2,third=0;
for(int i=3;i<=target;i++){
third =first +second;
first = second;
second=third;
}
return third;
}
递归算法时间复杂度非常之高,此题中复杂度在800-990ms之间,而迭代的时间复杂度为15ms。
六、
(大佬!)
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
思路:
关于本题,前提是n个台阶会有一次n阶的跳法。分析如下:
f(1) = 1
f(2) = f(2-1) + f(2-2) //f(2-2) 表示2阶一次跳2阶的次数。
f(3) = f(3-1) + f(3-2) + f(3-3)
...
f(n) = f(n-1) + f(n-2) + f(n-3) + ... + f(n-(n-1)) + f(n-n)
说明:
1)这里的f(n) 代表的是n个台阶有一次1,2,...n阶的 跳法数。
2)n = 1时,只有1种跳法,f(1) = 1
3) n = 2时,会有两个跳得方式,一次1阶或者2阶,这回归到了问题(1) ,f(2) = f(2-1) + f(2-2)
4) n = 3时,会有三种跳得方式,1阶、2阶、3阶,
那么就是第一次跳出1阶后面剩下:f(3-1);第一次跳出2阶,剩下f(3-2);第一次3阶,那么剩下f(3-3)
因此结论是f(3) = f(3-1)+f(3-2)+f(3-3)
5) n = n时,会有n中跳的方式,1阶、2阶...n阶,得出结论:
f(n) = f(n-1)+f(n-2)+...+f(n-(n-1)) + f(n-n) => f(0) + f(1) + f(2) + f(3) + ... + f(n-1)
6) 由以上已经是一种结论,但是为了简单,我们可以继续简化:
f(n-1) = f(0) + f(1)+f(2)+f(3) + ... + f((n-1)-1) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2)
f(n) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2) + f(n-1) = f(n-1) + f(n-1)
可以得出:
f(n) = 2*f(n-1)
7) 得出最终结论,在n阶台阶,一次有1、2、...n阶的跳的方式时,总得跳法为:
| 1 ,(n=0 )
f(n) = | 1 ,(n=1 )
| 2*f(n-1),(n>=2)
思路:
因为n级台阶,第一步有n种跳法:跳1级、跳2级、到跳n级
跳1级,剩下n-1级,则剩下跳法是f(n-1)
跳2级,剩下n-2级,则剩下跳法是f(n-2)
所以f(n)=f(n-1)+f(n-2)+...+f(1)
因为f(n-1)=f(n-2)+f(n-3)+...+f(1)
所以f(n)=2*f(n-1)
public class Solution {
public int JumpFloorII(int target) {
if (target <= 0) {
return -1;
} else if (target == 1) {
return 1;
} else {
return 2 * JumpFloorII(target - 1);
}
}
}
七、
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
解答(自己):
public int NumberOf1(int n) {
int shang=Integer.MAX_VALUE;
int yushu;
int sum=0;
if(n>0) {
while (shang != 0) {
shang = n / 2;
yushu = n % 2;
if (yushu == 1)
sum++;
n = shang;
}
}else if (n<0){
n = Integer.MAX_VALUE+n+1;
sum=1;
while (shang != 0) {
shang = n / 2;
yushu = n % 2;
if (yushu == 1)
sum++;
n = shang;
}
}
else {
return 0;
}
return sum;
}
思路:
如果一个整数不为0,那么这个整数的二进制至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。
举个例子:一个二进制数1100,从右边数起第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011.我们发现减1的结果是把最右边的一个1开始的所有位都取反了。这个时候如果我们再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。如1100&1011=1000.也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。
解答(大佬):
public int NumberOf1(int n) {
int count = 0;
while(n!= 0){
count++;
n = n & (n - 1);
}
return count;
}
例子: n=11,11=1011, return 3
n=n&(n-1), 即: 1011&1010=1010
n=n&(n-1), 即: 1010&1001=1000
n=n&(n-1), 即: 1000&0111=0000
八、
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,
所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
思路:
遍历数组中每一个数字,奇数放在ListA中,偶数放在ListB中,然后再A,B重新赋给Array
解答(自己):
public void reOrderArray(int [] array) {
ArrayList a = new ArrayList();
ArrayList b = new ArrayList();
for(int c:array){
if(c%2==1)
a.add(c);
else
b.add(c);
}
for(int i=0;i<a.size();i++){
array[i]=(int)a.get(i);
}
for(int i=0;i<b.size();i++){
array[i+a.size()]=(int)b.get(i);
}
}
思路:类似冒泡算法,前偶后奇数就交换
解答(大佬):
void reOrderArray(vector<int> &array) {
for (int i = 0; i < array.size();i++)
{
for (int j = array.size() - 1; j>i;j--)
{
if (array[j] % 2 == 1 && array[j - 1]%2 == 0) //前偶后奇交换
{
swap(array[j], array[j-1]);
}
}
}
}
九、
一个数组中有n对相同数字,有一个不同数字,找出不同数字,数组为空则返回0。
思路:
int[] numarry = new int[]{1,2,3,2,3};
关于上边的这个结果是什么,你只需要知道异或运算的特点就可以了,比如1,2,3,2,3 ,既然异或运算满足上边的交换规则,对于1^2^3^2^3 这样的异或运算,我们换一下位置(2^2)^(3^3)^1 ,通过两个相同的数进行异或运算得到0 ,那最终就会是0^0^1 ,最后会得到1 。
解答(大佬):
public static int selectNum(int[] x){
if(x.length==0)
return 0;
int num=x[0];
for(int i=1;i<x.length;i++)
num = num ^ x[i];
return num;
}
十、
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
思路:
进队操作则对stack1进行push,出队操作分为两种,当stack2不为空时,则对stack2进行pop,若stack2为空,则将stack1 pop出的数据push入stack2,
再对stack2进行pop,若stack1也为空,则NullPointException
解答:
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
if(!stack2.empty())
return stack2.pop();
while(!stack1.empty()){
stack2.push(stack1.pop());
}
return stack2.pop();
}
}
十一、
输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
思路:
将链表里的值取出放到ArrayList中,然后利用Collections里的reverse()方法反转ArrayList
解答:
import java.util.ArrayList;
import java.util.Collections;
public static ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> newI= new ArrayList<Integer>();
if(listNode!=null) {
newI.add(listNode.val);
while (listNode.next != null) {
listNode = listNode.next;
newI.add(listNode.val);
}
Collections.reverse(newI);
}
return newI;
}
思路:
利用栈先进后出的原理,先将链表里的值压入栈中,再将栈中的值取出放入ArrayList
public static ArrayList<Integer> printListFromTailToHead(Person listNode) {
ArrayList<Integer> newI= new ArrayList<Integer>();
Stack<Integer> sta = new Stack<Integer>();
/*压入栈*/
if(listNode!=null)
{
sta.push(listNode.val);
while(listNode.next!=null){
sta.push(listNode.next.val);
listNode = listNode.next;
}
while(!sta.empty()){
newI.add(sta.pop());
}
}
return newI;
}
十二、
输入一个链表,输出该链表中倒数第k个结点。
思路:
在getLength()方法中得到链表的长度,在主函数中将链表移动size-k次
解答(大佬):
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
int size=getLength(head);
if(size==k)
return head;
else if(size<k)
return null;
for(int i=0;i<size-k;i++){
head=head.next;
}
return head;
}
public static int getLength(ListNode head){
int length=1;
if(head==null)
return 0;
while(head.next!=null){
length=length+1;
head=head.next;
}
return length;
}
}
最佳代码:Java代码,通过校验。代码思路如下:两个指针,先让第一个指针和第二个指针都指向头结点,然后再让第一个指正走(k-1)步,到达第k个节点。然后两个指针同时往后移动,当第一个结点到达末尾的时候,第二个结点所在位置就是倒数第k个节点了。
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
if(head==null||k<=0){
return null;
}
ListNode pre=head;
ListNode last=head;
for(int i=1;i<k;i++){
if(pre.next!=null){
pre=pre.next;
}else{
return null;
}
}
while(pre.next!=null){
pre = pre.next;
last=last.next;
}
return last;
}
}
十三、
输入一个有符号整数,输出该整数的反转值。
思路:
利用StringBuffer的reverse()方法,反转其值
解答:
public static int change(int x){
boolean flag =true;
StringBuffer sb;
if(x>=0){
String str = String.valueOf(x);
sb = new StringBuffer(str);
sb.reverse();
}else {
flag=false;
x=-x;
String str = String.valueOf(x);
sb = new StringBuffer(str);
sb.reverse();
}
return !flag?(-(Integer.valueOf(sb.toString()))):Integer.valueOf(sb.toString());
}
十四、
若干个硬币,求和为N元的最小硬币数(动态规划)
思路:
若硬币为{1,2,5}元,要11元的解集,那么有5+5+1,只需要三个硬币数。
若我们需要0元,那么只要0个硬币,若要1元,需要1个硬币。
若为2元,那么需要1个两元硬币,或者两个1元硬币,但是最小硬币数,所以只需要一个2元硬币就够了。
若为3元,需要1+2,两个硬币。
若为4元,需要2+2,需要两个硬币.....
得出结论,f(n)=f(n-x)+1
n表示n元,f(n)表示n元需要的最小硬币数,x表示我们有的硬币大小,如1,2,5元
f(n)=f(n-x)+1,可解读为:n元的最小硬币数=(n-x)元的硬币+1
若n=11,假设全部用1元,那么需要11个1元硬币,但是最小硬币数应为5+5+1元,3个硬币,
那么有f(11)=f(11-5)+1,
f(6)=f(6-5)+1,
f(1)=f(1-1)+1,
f(0)=0.
所以往上推,有f(0)=0,f(1)=1,f(6)=2,f(11)=3
但是,需要满足前提条件
1.n>x,N元要大于取出的硬币数值,如,N=3,那么我们就不能取5元,因为5>3
2.f(n-x)+1要小于原来的f(n),否则需要的硬币数反而变多了
4元,假设需要4个1元硬币,那么我们就不取1元的,直接取1元后面的2元,那么有
f(4)=f(4-2)+1=f(2)+1
f(2)=f(2-2)+1=1
所以f(4)=2
解答:
public static void main(String[] args) throws Exception {
int[] coin={1,2,5};
int sum=11; //sum表示N元
int[] use = new int[sum+1];
use[0]=0;
for(int i=1;i<=sum;i++){
use[i]=i; //use=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
}
for(int i=1;i<=sum;i++){
for(int j=0;j<3;j++){
if(i>=coin[j]&&use[i]>(use[i-coin[j]]+1)){
use[i] = use[i- coin[j] ] + 1;
}
}
}
System.out.println(use[sum]);
}
转载于:https://www.cnblogs.com/zhuii/p/9940290.html
算法编程-不定时更新相关推荐
- 排序算法(不定时更新~)
插入排序: /*** 插入排序* 初始时,拿第二个和第一个比较,如果第二个小于第一个,两个交换* 当进行到第N次时,前面的N-1个顺序应该是正确的* 拿第N个和前面的N-1个数比较,如果第M个小于N, ...
- [Android Traffic] 调整定时更新的频率(C2DM与退避算法)
转载自: http://blog.csdn.net/kesenhoo/article/details/7395253 Minimizing the Effect of Regular Updates[ ...
- 【面试锦囊】14种模式搞定面试算法编程题(1-7)
面试锦囊之知识整理系列 面试锦囊系列一直有收到大家的反馈,包括后台内推成功的消息.朋友的同事从创业小公司成功跳到huawei等等,非常高兴小破号的这些整理分享能够真正地帮助到大家,以后也会继续.为了更 ...
- 【面试锦囊】14种模式搞定面试算法编程题(8-14)
面试锦囊之知识整理系列 面试锦囊系列一直有收到大家的反馈,包括后台内推成功的消息.朋友的同事从创业小公司成功跳到huawei等等,非常高兴小破号的这些整理分享能够真正地帮助到大家,以后也会继续.为了更 ...
- 14种模式解决面试算法编程题(PART I)
万万没想到,暑假还没开始,有些公司的秋招提前批已经来了-很慌-数据结构和算法题可以说是秋招笔试面试必考的内容,如果你还不够熟练(just like me),那就要从现在开始疯狂刷题了啊朋友们. 附上我 ...
- 2022程序员都推荐的算法编程课程终于来了!新手从入门到面试考点全覆盖,学到就是赚到!...
还在自学算法&编程像个无头苍蝇一样没有头绪?看完这篇文章帮你解决问题! (❗干货警告:文末附2022大厂最新面试真题~) 程序员作为一个高薪行业已经明显出现"内卷"情况了! ...
- AirSim学习和踩坑记录(不定时更新)
版权声明:本文为博主原创文章,遵循Creative Commons - Attribution-ShareAlike 4.0 International - CC BY-SA 4.0版权协议,转载请附 ...
- 【原创】强化学习笔记|从零开始学习PPO算法编程(pytorch版本)
从零开始学习PPO算法编程(pytorch版本)_melody_cjw的博客-CSDN博客_ppo算法 pytorch 从零开始学习PPO算法编程(pytorch版本)(二)_melody_cjw的博 ...
- 算法编程Algos Programming
算法编程Algos Programming 不同算法的集合,用于编程比赛,如ACM ICPC. 算法按主题划分.大多数算法都可以从文件中按原样运行.每种算法都有一个参考问题,并对其时间和空间复杂度作了 ...
- apue第四章习题的一些拙见(不定时更新)
写在前面:最近要期末考试,看来真的是要不定时更新啦XD apue4.1: 由于在这里lstat是不跟随符号文件的,而stat是跟随符号文件的,这样一来,如果使用stat,而不使用lstat那么就无法观 ...
最新文章
- 小鱼便签_同样是写便签,这样更酷
- HashMap如何在Java中工作
- 基于JAVA+SpringMVC+Mybatis+MYSQL的图书馆预约占座管理系统
- Python:使用threading模块实现多线程编程三[threading.Thread类的重要函数]
- fstatfs/statfs详解
- 无线网卡802.11n、 Intel 5100 AGN
- Atitit zip压缩过滤器 的模块功能语实现attilax总结 1.1. 一般可以使用webserver自带的实现,。如果实现的不好或者不好配置的,或者需要精细化控制的,可以自己使用过滤器实现。
- 劢领AT| 五分钟,零基础玩转Wing中国电信物联网开放平台
- excel快速便捷批量填充
- 重装Win7系统步骤和详细教程
- 在视图列中显示文档所有读者和作者
- H5怎么制作?快来看这个H5制作平台的案例你可能就明白了
- linux slub分配器,Vi Linux内存 之 Slub分配器(六)
- 《登黄山偶感》艺术品赏
- QA之道知多少(一) 初出茅庐
- 美拍作者页视频的保存的方法
- 新浪云sae怎么上传php代码,如何在新浪SAE中上传文件和在线修改模板
- sklearn数据降维之字典学习
- 数据库隔离级别的理解
- MT7688详细芯片资料下载 MT7688规格说明简介
热门文章
- wpf silverlight的Behavior
- R_空间插值_必知必会(二)
- 用data.table语句批量处理变量
- visual studio 中将选中代码相同的代码的颜色设置,修改高亮颜色
- 适合程序员演讲的定场诗
- Kia#39;s Calculation(贪心)
- “敏捷开发”怎么就“敏捷”了
- 1225 八数码难题
- Java面向对象的继承
- Cocos数据篇[3.4](3) ——XML数据操作