java二维数组高纬低纬_2018-05-17 第十一天
一、數(shù)組
(一)數(shù)組的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):1:數(shù)組通過下標(biāo)訪問元素的效率很高。指定下標(biāo)n的元素的地址:首地址+n*元素類型字節(jié)數(shù)。
2:數(shù)組可以保存若干個(gè)元素的值。
缺點(diǎn):1:數(shù)組的長度是不能更改的。
2:數(shù)組進(jìn)行元素的刪除和插入操作的時(shí)候,效率比較低。需要移動(dòng)大量的元素。
3:數(shù)組元素的類型只能是一種。
4:數(shù)組通過內(nèi)容查找元素的效率是比較低的。
5:數(shù)組的元素是連續(xù)分配的,那么必須在堆內(nèi)存中找到連續(xù)的指定內(nèi)存空間才能容納數(shù)組的所有的數(shù)據(jù)。對(duì)內(nèi)存要求稍微多一些。
6:數(shù)組沒有提供任何的封裝,所有對(duì)元素的操作,都是通過自定義方法來實(shí)現(xiàn)的。對(duì)數(shù)組元素的操作比較麻煩。
java 提供了一整套的用于管理對(duì)象的容器。集合框架 collection framework。可以有效解決這些缺點(diǎn)。
(二)java.util.Arrays 工具類
jdk 提供了一個(gè)工具類:專門用于處理數(shù)組的工具類。
//一定記得導(dǎo)入Arrays。
import java.util.Arrays;
public class Arrays extends Object
此類包含用來操作數(shù)組(比如排序和搜索)的各種方法
常用方法:
static int binarySearch(byte[] a, byte key)
使用二分搜索法來搜索指定的byte 型數(shù)組,以獲得指定的值。
static int binarySearch(byte[] a, int fromIndex, int toIndex, byte key)
使用二分搜索法來搜索指定的byte 型數(shù)組的范圍,以獲得指定的值。
static boolean[] copyOf(boolean[] original, int newLength)
復(fù)制指定的數(shù)組,截取或用false 填充(如有必要),以使副本具有指定的長度。
static void sort(byte[] a)
對(duì)指定的byte 型數(shù)組按數(shù)字升序進(jìn)行排序。
static String toString(boolean[] a)
返回指定數(shù)組內(nèi)容的字符串表示形式。
static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
從指定源數(shù)組中復(fù)制一個(gè)數(shù)組,復(fù)制從指定的位置開始,到目標(biāo)數(shù)組的指定位置結(jié)束。
(三)main方法傳遞參數(shù)(了解):
main 方法的 字符串?dāng)?shù)組 參數(shù)的作用:
可以用來接收控制臺(tái)在解釋執(zhí)行的時(shí)候,輸入的一系列的字符串內(nèi)容。多個(gè)字符串對(duì)象可以使用空格分隔輸入即可。
public class TestString{
public static void main(String[] args){
for(String str : args){
print(str);
}
String str = "";
String[] strs = {"123","123","123","123","123","123"};
}
public static void print(String str){
System.out.println(str);
}
}
(四) 變參
變參方法:在jdk1.5 之后提供的功能。
語法:參數(shù)列表(接收的數(shù)據(jù)的類型 ... 變量名)
例子(boolean ... values)
變參參數(shù)的特點(diǎn):
1:變參參數(shù)可以接收的參數(shù)的數(shù)量[0-N]
2: 如果有定參的方法,有變參的方法,那么優(yōu)先匹配定參的方法。
3:一個(gè)方法最多只能有一個(gè)變參參數(shù),而且必須在參數(shù)列表的末尾。
4:方法在處理變參參數(shù)的時(shí)候,就當(dāng)數(shù)組來處理即可。底層使用數(shù)組實(shí)現(xiàn)的。
5:變參參數(shù)既可以接收 數(shù)據(jù)類型若干個(gè)實(shí)參的值,還可以接收一個(gè)該類型的數(shù)組。
例:
需求:使用變參實(shí)現(xiàn):寫一個(gè)方法,可以接收任意個(gè)int類型的參數(shù),將這若干個(gè)數(shù)據(jù)中的最大值返回。
//變參方法
public class TestChangeArgs{
public static void main(String[] args){
System.out.println(max());
System.out.println(max(1));
System.out.println(max(2,5));
System.out.println(max(3,4,8));
System.out.println(max(2,5,67,89));
System.out.println(max(32,54,67,7,56,45,34));
int[] arr = {45,34,32,54,76};
System.out.println(max(arr));
}
public static int max(int a, int b){
System.out.println("2個(gè)參數(shù)的方法");
return a > ?b ? a : b;
}
public static int max(int a, int b ,int c){
System.out.println("3個(gè)參數(shù)的方法");
return a > ?b ? (a > c ? a : c) : (b > c ? b : c);
}
//如果有方法可以接收參數(shù)的數(shù)量是任意個(gè)[0--n]?
public static int max(int ... values){
System.out.println("變參參數(shù)的方法");
if(values == null)return -1;
if(values.length == 0)return -2;
int max = values[0];
for(int i = 1;i< values.length;i++){
if(values[i] > max){
max = values[i];
}
}
return max;
}
public static void test(int a, int ... values){
}
}
(五)多維數(shù)組
一維數(shù)組:int[] values = new int[10];
二維數(shù)組:本質(zhì)上還是一維數(shù)組
int[] array;
int[][] array;
初始化的方式:
動(dòng)態(tài)的:int[][] array = new int[7][9];//代表了這個(gè)數(shù)組是一個(gè)7個(gè)元素的一維數(shù)組,每個(gè)一維數(shù)組的元素又是一個(gè)一維數(shù)組,最終的一維數(shù)組的元素的個(gè)數(shù)是9個(gè)。
其他樣式:int[][] arr = new int[1][1];
int[] arr[] ?= new int[1][2];
int [][]arr = new int[2][3];
int arr[][] = new int[2][5];
靜態(tài)方式:int[][] array1 = new int[][]{
{1,34,5,65,89},
{1,34,5},
{1,65},
{1,34,5,65,5,4,43,23}
};
int[][] array1 = {
{1,34,5,65,89},
{1,34,5},
{1,65},
{1,34,5,65,5,4,43,23}
};
//多維數(shù)組
import java.util.Arrays;
public class TestArray6{
public static void main(String[] args){
//高緯 代表的是有幾個(gè)一維數(shù)組,低緯的數(shù)值代表的是每一個(gè)一維數(shù)組的元素的個(gè)數(shù)。
int[] array[] = new int[3][];
System.out.println(Arrays.toString(array));
//可以將每個(gè)一維數(shù)組的長度控制的不同。單獨(dú)進(jìn)行空間的分配。
array[0] = new int[3];
array[1] = new int[6];
array[2] = new int[1];
System.out.println(Arrays.toString(array));
System.out.println(array.length);//3
System.out.println(array[1].length);//6
int[][] array1 = new int[][]{
{1,34,5,65,89},
{1,34,5},
{1,65},
{1,34,5,65,5,4,43,23}
};
System.out.println(array1.length);//4
System.out.println(array1[2].length);//2
}
}
多維數(shù)組內(nèi)存圖:
例1:
//使用二維數(shù)組中的元素,存儲(chǔ)九九乘法表的結(jié)果,最后在將結(jié)果打印實(shí)現(xiàn)九九乘法表的效果。
public static void test(){
//先對(duì)二維數(shù)組進(jìn)行高緯空間的分配。
final int LEN = 9;
int[][] nine = new int[9][];
//然后在對(duì)每個(gè)一維數(shù)組進(jìn)行單獨(dú)的空間的分配。
for(int i=0;i
nine[i] = new int[i+1];
}
//在使用for 循環(huán) 將結(jié)果打印。
for(int i=1;i<=LEN;i++){
for(int j=1;j<=i;j++){
//使用數(shù)組元素保存
nine[i-1][j-1] = j * i;
System.out.print(j+"*"+i+"="+nine[i-1][j-1]+"; ");
}
System.out.println();
}
}
例2:偏算法,可以了解了解
//螺旋數(shù)組
public class TestArray11{
public static void main(String[] args){
int count = 6;
int[][] ints = test(count);
for (int i = 0; i < count; i++) {
for (int j = 0; j < count; j++) {
System.out.print(ints[i][j] + "\t");
}
System.out.println();
}
}
private static int[][] test(int count){
int[][] ints = new int[count][count];
final int RIGHT = 0;
final int DOWN = 1;
final int LEFT = 2;
final int UP = 3;
int dir = RIGHT;
int curRow = 0;
int curCol = 0;
for (int i = 1; i <= count * count; i++) {
switch(dir){
case RIGHT:
if(curCol < count){
if(ints[curRow][curCol] == 0){
ints[curRow][curCol] = i;
curCol ++;
}else{
curCol --;
dir = DOWN;
if(ints[curRow + 1][curCol] != 0){
return ints;
}else{
curRow ++;
ints[curRow][curCol] = i;
curRow ++;
}
}
}else{
curCol --;
dir = DOWN;
if(ints[curRow + 1][curCol] != 0){
return ints;
}else{
curRow ++;
ints[curRow][curCol] = i;
curRow ++;
}
}
break;
case DOWN:
if(curRow < count){
if(ints[curRow][curCol] == 0){
ints[curRow][curCol] = i;
curRow ++;
}else{
curRow --;
dir = LEFT;
if(ints[curRow][curCol-1] != 0){
return ints;
}else{
curCol --;
ints[curRow][curCol] = i;
curCol --;
}
}
}else{
curRow --;
dir = LEFT;
if(ints[curRow][curCol-1] != 0){
return ints;
}else{
curCol --;
ints[curRow][curCol] = i;
curCol --;
}
}
break;
case LEFT:
if(curCol >=0){
if(ints[curRow][curCol] == 0){
ints[curRow][curCol] = i;
curCol --;
}else{
dir = UP;
curCol ++;
if(ints[curRow - 1][curCol] != 0){
return ints;
}else{
ints[--curRow][curCol] = i;
curRow --;
}
}
}else{
curCol ++;
dir = UP;
if(ints[curRow - 1][curCol] != 0){
return ints;
}else{
ints[--curRow][curCol] = i;
curRow --;
}
}
break;
case UP:
if(curRow >=0){
if(ints[curRow][curCol] == 0){
ints[curRow][curCol] = i;
curRow --;
}else{
dir = RIGHT;
curRow++;
if(ints[curRow][curCol+1] != 0){
return ints;
}else{
ints[curRow][++curCol] = i;
++curCol;
}
}
}else{
curRow ++;
dir = RIGHT;
if(ints[curRow][curCol+1] != 0){
return ints;
}else{
ints[curRow][++curCol] = i;
++curCol;
}
}
break;
}
}
return ints;
}
}
二、遞歸
概念:遞歸調(diào)用:方法直接或者間接的調(diào)用自身的過程。
void a(int n){
//a(n-1);
b(n-1);
}
void b(int n){
a(n-1);
}
什么樣的問題可以使用遞歸調(diào)用來解決?
1:一個(gè)問題可以被分解為若干個(gè)子問題。
2:子問題的解決方案和問題的解決方案一致。
3:最終問題的解決依賴于子問題的解決。
例1:
//求n 的階乘。
n!:n*(n-1)*(n-2)*...2*1;
1:一個(gè)問題可以被分解為若干個(gè)子問題。
2:子問題的解決方案和問題的解決方案一致。
3:最終問題的解決依賴于子問題的解決。
5! = 5 * 4 !
4! = 4 * 3!
3! = 3 * 2!
2! = 2 * 1!
1! = 1;
//求n 的階乘 ?時(shí)間復(fù)雜度 ?T(n) = O(n); ?空間復(fù)雜度 S(n) = O(n)
public static int fac(int n){
int result = 0;
if(n == 1){
result = 1;
}else{
result = n * fac(n-1);
}
return result;
}
例2:
//斐波那契數(shù)列 ?前兩個(gè)數(shù)都是1,從第三個(gè)數(shù)開始,是前兩個(gè)數(shù)之和
//1,1,2,3,5,8,13。。。。 T(n) = O(n);
//求第n 個(gè)位置上的斐波那契數(shù)列的值
public static int febo(int n){
if(n == 1 || n == 2){
return 1;
}else{
return febo(n-1) + febo(n-2);
}
}
遞歸調(diào)用的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):代碼簡單,思路比較簡單。
缺點(diǎn):對(duì)棧內(nèi)存的消耗比較大,如果控制不好,那么就會(huì)造成棧內(nèi)存溢出。
遞歸調(diào)用的過程中,必須在某些情況下存在自己不調(diào)用自己的情況。以保證程序可以在合適的時(shí)候正確返回。
三、算法(algorithm )(了解)
是指令的集合,是為解決特定問題而規(guī)定的一系列操作。
簡單的說,算法就是計(jì)算機(jī)解題的過程。
舉例:如何求0+1+2+3+...10000=?
算法1:依次相加 ?while do-while ?for
算法2:高斯解法:首尾相加*50 ???(1+10000)*10000/2 ???100*101/2
算法3:使用遞歸實(shí)現(xiàn): sum(100) = sum(99)+100 ??sum(99)= sum(98)+99 ..... ??sum(2) = sum(1)+2 ??sum(1) = 1
評(píng)價(jià)算法優(yōu)劣的依據(jù):復(fù)雜度(時(shí)間復(fù)雜度和空間復(fù)雜度)
時(shí)間復(fù)雜度是指執(zhí)行算法所需要的計(jì)算工作量
空間復(fù)雜度是指執(zhí)行這個(gè)算法所需要的內(nèi)存空間
(一)時(shí)間復(fù)雜度(Time Complexity))定義
時(shí)間頻度:
一個(gè)算法執(zhí)行所耗費(fèi)的時(shí)間,從理論上是不能算出來的,必須上機(jī)運(yùn)行測試才能知道。
但我們不可能也沒有必要對(duì)每個(gè)算法都上機(jī)測試。
一個(gè)算法花費(fèi)的時(shí)間與算法中語句的執(zhí)行次數(shù)成正比例,哪個(gè)算法中語句執(zhí)行次數(shù)多,它花費(fèi)時(shí)間就多。
一個(gè)算法中的語句執(zhí)行次數(shù)稱為語句頻度或時(shí)間頻度,表示為T(n),n表示問題的規(guī)模
時(shí)間復(fù)雜度
但有時(shí)我們想知道它變化時(shí)呈現(xiàn)什么規(guī)律,想知道問題的規(guī)模,而不是具體的次數(shù),此時(shí)引入時(shí)間復(fù)雜度。
一般情況下,算法中基本操作重復(fù)執(zhí)行的次數(shù)是問題規(guī)模n的某個(gè)函數(shù),用T(n)表示,
若有某個(gè)輔助函數(shù)f(n),使得當(dāng)n趨近于無窮大時(shí),T(n)/f(n)的極限值為不等于零的常數(shù),則稱f(n)是T(n)的同數(shù)量級(jí)函數(shù)。
記作T(n)=O(f(n)),稱O(f(n)) 為算法的漸進(jìn)時(shí)間復(fù)雜度,簡稱時(shí)間復(fù)雜度。
T(n)=O(f(n))
或者說:時(shí)間復(fù)雜度就是時(shí)間頻度去掉低階項(xiàng)和首項(xiàng)常數(shù)。
注意:時(shí)間頻度與時(shí)間復(fù)雜度是不同的,時(shí)間頻度不同但時(shí)間復(fù)雜度可能相同。
比如:某兩個(gè)算法的時(shí)間頻度是T(n) = 100000n2+10n+6 ???T(n) = 10n2+10n+6 ??T(n) = n2
但是時(shí)間復(fù)雜度都是T(n) = O(n2)
總結(jié):隨著n 的增大,如果兩個(gè)頻度的函數(shù)的結(jié)果是無限接近的,那么這兩個(gè)算法的時(shí)間復(fù)雜度是相同的。
時(shí)間復(fù)雜度考量的是算法的變化的趨勢。
最壞時(shí)間復(fù)雜度和平均時(shí)間復(fù)雜度
最壞情況下的時(shí)間復(fù)雜度稱最壞時(shí)間復(fù)雜度。一般不特別說明,討論的時(shí)間復(fù)雜度均是最壞情況下的時(shí)間復(fù)雜度。
這樣做的原因是:最壞情況下的時(shí)間復(fù)雜度是算法在任何輸入實(shí)例上運(yùn)行時(shí)間的上界,這就保證了算法的運(yùn)行時(shí)間不會(huì)比任何更長。
在最壞情況下的時(shí)間復(fù)雜度為T(n)=O(n),它表示對(duì)于任何輸入實(shí)例,該算法的運(yùn)行時(shí)間不可能大于O(n)。
平均時(shí)間復(fù)雜度是指所有可能的輸入實(shí)例均以等概率出現(xiàn)的情況下,算法的期望運(yùn)行時(shí)間。鑒于平均復(fù)雜度
第一,難計(jì)算
第二,有很多算法的平均情況和最差情況的復(fù)雜度是一樣的。
所以一般討論最壞時(shí)間復(fù)雜度
比如我要求你在字典里查同一個(gè)字,告訴我這個(gè)字在字典的那一頁。
如果一頁一頁的翻,你需要多少時(shí)間呢?
最優(yōu)的情況就是這個(gè)字在第一頁,
最壞的情況就是這個(gè)字是整本字典的最后一個(gè)字。
所以即使我故意為難你,你也不會(huì)花費(fèi)比找整本字典最后一個(gè)字還長的時(shí)間。
當(dāng)然,此時(shí)聰明的你就會(huì)想用部首、筆畫等去查,才不要傻乎乎的一頁一頁翻,
此時(shí)的你就會(huì)擇優(yōu)選擇,因?yàn)榇藭r(shí)你最壞得情況就是我給你部首筆畫最多、除部首外筆畫最多的一個(gè)超級(jí)復(fù)雜的一個(gè)字,但顯然比翻整本字典快得多。
為了進(jìn)一步說明算法的時(shí)間復(fù)雜度,我們定義Ο、Ω、Θ符號(hào)。
Ο(歐米可榮)符號(hào)給出了算法時(shí)間復(fù)雜度的上界(最壞情況<=),比如T(n) =O(n2)
Ω(歐米伽)符號(hào)給出了時(shí)間復(fù)雜度的下界(最好情況>=),比如T(n) =Ω(n2)
而Θ(西塔)給出了算法時(shí)間復(fù)雜度的精確階(最好和最壞是同一個(gè)階=),比如T(n) =Θ(n2)
時(shí)間復(fù)雜度計(jì)算
根本沒有必要計(jì)算時(shí)間頻度,即使計(jì)算處理還要忽略常量、低次冪和最高次冪的系數(shù),所以可以采用如下簡單方法:
⑴ 找出算法中的基本語句;
算法中執(zhí)行次數(shù)最多的那條語句就是基本語句,通常是最內(nèi)層循環(huán)的循環(huán)體。
⑵ 計(jì)算基本語句的執(zhí)行次數(shù)的數(shù)量級(jí);
只需計(jì)算基本語句執(zhí)行次數(shù)的數(shù)量級(jí),這就意味著只要保證基本語句執(zhí)行次數(shù)的函數(shù)中的最高次冪正確即可,
可以忽略所有低次冪和最高次冪的系數(shù)。這樣能夠簡化算法分析,并且使注意力集中在最重要的一點(diǎn)上:增長率。
⑶ 用大Ο記號(hào)表示算法的時(shí)間性能。
將基本語句執(zhí)行次數(shù)的數(shù)量級(jí)放入大Ο記號(hào)中。
總結(jié):先找出基本的執(zhí)行單元的語句。然后算出語句的執(zhí)行的頻度,去掉低階項(xiàng),常數(shù)項(xiàng),去掉最高階的系數(shù)。
T(n) = O(f(n));
T(n) = O(n^2)
時(shí)間復(fù)雜度舉例
一個(gè)簡單語句的時(shí)間復(fù)雜度為O(1)。
int count=0;
100個(gè)簡單語句的時(shí)間復(fù)雜度也為O(1)。(100是常數(shù),不是趨向無窮大的n)
int count=0;
如果一個(gè)算法隨著問題規(guī)模的增大,執(zhí)行的基本語句的次數(shù)都是一個(gè)定值,那么時(shí)間復(fù)雜度都是O(1)
T(n) = O(1);
一個(gè)循環(huán)的時(shí)間復(fù)雜度為O(n)。
int n=8, count=0;
for (int i=1; i<=n; i++)
count++;
T(n)=O(n)
時(shí)間復(fù)雜度為O(log2?n)的循環(huán)語句。
int n=8, count=0;
for (int i=1; i<=n;i*=2)
count++;
n=2 ??2
n=4 ??3
n=8 ??4
n=16 5
230=1024*1024*1024 = 1000*1000*1000=10億
時(shí)間復(fù)雜度為O(n2)的二重循環(huán)。
int n=8, count=0;
for (int i=1; i<=100n; i++)
for (int j=1; j<=10n; j++)
count++;
時(shí)間復(fù)雜度為O(nlog2n)的二重循環(huán)。
int n=8, count=0;
for (int i=1; i<=n; i*=2)
for (int j=1; j<=n; j++)
count++;
時(shí)間復(fù)雜度為O(n2)的二重循環(huán)。
int n=8, count=0;
for (int i=1; i<=n; i++)
for (int j=1;j<=i; j++)
count++;
1+2+3+4....+n=(1+n)*n/2
需要復(fù)雜些數(shù)學(xué)運(yùn)算:1+2+3+.....+n=(n+1)*n/2 ?時(shí)間復(fù)雜度是 O(n2)
后面講解查找和排序算法時(shí)會(huì)大量的設(shè)計(jì)時(shí)間復(fù)雜度,作為選擇查找和排序算法的重要依據(jù)
常用的時(shí)間復(fù)雜度級(jí)別
常數(shù)階O(1)
對(duì)數(shù)階O(log2n)
線性階O(n)
線性對(duì)數(shù)階O(n*log2n)
平方階O(n2)
立方階O(n3)
...
k次方階O(nk)
指數(shù)階O(2n)
階乘階O(n!)
上面各種時(shí)間復(fù)雜度級(jí)別,執(zhí)行效率越來越低。
大家發(fā)現(xiàn)對(duì)數(shù)階O(log2n)和線性階O(n)的效率差異了嗎,當(dāng)n=10的8次方(1億)時(shí),執(zhí)行此時(shí)一個(gè)是1億次,一個(gè)是8次。
所以編寫算法時(shí)一定要注意時(shí)間復(fù)雜度的選擇。
空間復(fù)雜度計(jì)算:
表示方法
S(n) = O(f(n));
固定的變量的個(gè)數(shù)
S(n) = O(1);
例://1-n的累加和。
n 就是問題的規(guī)模。
1:使用while 循環(huán) sum +=i
T(n) = n;
T(n) = O(n).
2:高斯算法 ?(1+n)*n/2
T(n) = 1;
T(n) = O(1);
總結(jié)
以上是生活随笔為你收集整理的java二维数组高纬低纬_2018-05-17 第十一天的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: led控制器java_TM1668 Le
- 下一篇: python在匿名函数作和_跟光磊学Py