《剑指offer》-- 构建乘积数组、求1+2+3+...+n、不用加减乘除做加法、包含min函数的栈、用两个栈实现队列
?一、構建乘積數組:
1、題目:
給定一個數組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]。不能使用除法。
2、解題思路:
參考牛客網的“披薩大叔”:https://www.nowcoder.com/questionTerminal/94a4d381a68b47b7a8bed86f2975db46
B[i]的值可以看作下圖的矩陣中每行的乘積。
下三角用連乘可以很容求得,上三角,從下向上也是連乘。
因此我們的思路就很清晰了,先算下三角中的連乘,即我們先算出B[i]中的一部分,然后倒過來按上三角中的分布規律,把另一部分也乘進去。
3、代碼實現:
public class Test7 {public int[] multiply(int[] A) {int length= A.length;int[] B = new int[length];if(length!=0){B[0]=1;//計算下三角連乘for(int i = 1;i<length;i++){B[i]=B[i-1]*A[i-1];}int temp=1;//計算上三角連乘for(int j=length-2;j>=0;j--){temp=temp*A[j+1];B[j]=B[j]*temp;}}return B;} }?
?
二、求1+2+3+...+n
1、題目:
1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等關鍵字及條件判斷語句(A?B:C)。
2、解題思路:
利用&&的短路特性,&&就是邏輯與,邏輯與有個短路特點,前面為假,后面不計算。
3、代碼實現:
public class Solution {public int Sum_Solution(int n) {//利用&&的短路特性,&&就是邏輯與,邏輯與有個短路特點,前面為假,后面不計算。boolean result=true;int sum =0;result=(n>0) && ((sum=Sum_Solution(n-1))>0);sum=sum+n;return sum;} }?
?
三、不用加減乘除做加法:
1、題目:
寫一個函數,求兩個整數之和,要求在函數體內不得使用+、-、*、/四則運算符號。
2、解題思路:
首先看十進制是如何做的: 5+7=12,三步走:
第一步:相加各位的值,不算進位,得到2。
第二步:計算進位值,得到10. 如果這一步的進位值為0,那么第一步得到的值就是最終結果。
第三步:重復上述兩步,只是相加的值變成上述兩步的得到的結果2和10,得到12。
同樣我們可以用三步走的方式計算二進制值相加: 5-101,7-111 第一步:相加各位的值,不算進位,得到010,二進制每位相加就相當于各位做異或操作,101^111。
第二步:計算進位值,得到1010,相當于各位做與操作得到101,再向左移一位得到1010,(101&111)<<1。
第三步重復上述兩步, 各位相加 010^1010=1000,進位值為100=(010&1010)<<1。
? ? ?繼續重復上述兩步:1000^100 = 1100,進位值為0,跳出循環,1100為最終結果。
3、代碼實現:
public class Test25 {public int Add(int num1,int num2) {while(num2!=0){int temp=num1^num2;num2=(num1&num2)<<1;num1 = temp;}return num1;} }?
?
四、包含min函數的棧:
1、題目:
定義棧的數據結構,請在該類型中實現一個能夠得到棧中所含最小元素的min函數(時間復雜度應為O(1))。
2、第一種解題思路:
借助輔助棧存儲min的大小,自定義棧結構
? ? list ?3,4,2,5,1
? ? 輔助棧 3,3,2,2,1
每入棧一次,就與輔助棧頂比較大小,如果小就入棧,如果大就入棧當前的輔助棧的棧頂元素;
當出棧時,輔助棧也要出棧,這種做法可以保證輔助棧頂一定都當前棧的最小值
代碼實現:
public class Test7 {private int size;//數組容量private int min=Integer.MAX_VALUE;//最小元素private Stack<Integer> minStack = new Stack<Integer>();//輔助棧private Integer[] elements = new Integer[10];//數據入棧,每入棧一次,就與輔助棧頂比較大小,如果小就入棧,如果大就入棧當前的輔助棧的棧頂元素。public void push(int node){ensureCapacity(size+1);elements[size++]= node;if(node<=min){minStack.push(node);min=minStack.peek();}else{minStack.push(min);}}//數組擴容private void ensureCapacity(int i) {int len=elements.length;if(size>len){int newLen =(len*3)/2+1;//每次擴容的方式elements=Arrays.copyOf(elements, newLen);}}//元素出棧,當出棧時,輔助棧也要出棧,保證輔助棧頂一定都當前棧的最小值private void pop(){Integer top=top();if(top!=null){elements[size-1] =(Integer)null;}size--;minStack.pop();min=minStack.peek();}public int top(){if(!empty()){if(size-1>=0){return elements[size-1];}}return (Integer)null;}public boolean empty(){return size == 0;}public int min(){return min;} }3、第二種解題思路:
每次入棧2個元素,一個是入棧的元素本身,一個是當前棧元素的最小值。 ?如:入棧序列為2-3-1,則入棧后棧中元素序列為:2-2-3-2-1-1 * 用空間代價來換取時間代價:
代碼實現:
import java.util.Stack; import java.util.Arrays;public class Solution {private Stack<Integer> stack = new Stack<Integer>();public void push(int node) {if(stack.isEmpty()){stack.push(node);stack.push(node);}else{int temp = stack.peek();stack.push(node);if(temp<node){stack.push(temp);}else{stack.push(node);}}}public void pop() {stack.pop();stack.pop();}public int top() {return stack.get(stack.size()-2);}public int min() {return stack.peek();} }?
五、用兩個棧實現隊列:
1、題目描述:
兩個棧來實現一個隊列,完成隊列的Push和Pop操作。 隊列中的元素為int類型。
2、思路分析:
入隊:將元素進棧A
出隊:判斷棧B是否為空,如果為空,則將棧A中所有元素pop,并push進棧B,棧B出棧;如果不為空,棧B直接出棧。
3、代碼實現:
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.isEmpty()){while(!stack1.isEmpty()){stack2.push(stack1.pop());}}return stack2.pop();} }?
?
總結
以上是生活随笔為你收集整理的《剑指offer》-- 构建乘积数组、求1+2+3+...+n、不用加减乘除做加法、包含min函数的栈、用两个栈实现队列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《剑指offer》-- 和为S的连续整数
- 下一篇: 《剑指offer》-- 回溯法:矩阵中的