2015年10月30日 星期五

[Java]複製陣列的方法(System.arraycopy)

有時候需要建立一個新陣列,這個新陣列跟舊的陣列前面都一樣
只有最後幾個值不同或是加了幾個值

或是有兩個陣列,我們需要合併這兩個陣列的時候
除了用for迴圈把陣列一個一個倒進去以外
我們可以使用System的arraycopy方法

文件方法如下
arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

第一個src要放入的是被複製的陣列
srcPos是指定被複雜的陣列從第幾項開始複製

dest放入的是要複製的陣列
destPos是指定要複製的陣列從第幾項開始寫入

length放入的是你總共要複製幾項資料
以下是最常用的兩個範例


public class copyArrayDemo {



 public static void main(String[] args) {

  System.out.println("This is demo 1");

  int[] arr1 = {1,2,3};

  int[] arr2 = new int[arr1.length+1];

  System.arraycopy(arr1, 0, arr2, 0, arr1.length);

  arr2[arr1.length]= 4;

  // arr2 == {1,2,3,4}

  for(int item:arr2){

   System.out.println(item);

  }

  System.out.println("This is demo 2");



  

  String[] array1 = {"item1","item2","item3"};  

  String[] array2 = {"demo1","demo2","demo3"};

  

  

  String[] sum = new String[array1.length+array2.length];

  System.arraycopy(array1, 0, sum, 0, array1.length);

  System.arraycopy(array2, 0, sum, array1.length, array2.length);

  // sum =={"item1","item2","item3","demo1","demo2","demo3"}

  for(String item:sum){

   System.out.println(item);

  }    

 }

}

2015年10月26日 星期一

[Java]StringTokenizer

今天介紹一個除了split()方法以外,分割String的方法
StringTokenizer的方法主要有下列幾個

countTokens():可以知道你的String被Tokenizer分成幾段
hasMoreTokens():檢查StringTokenizer是否還有Token
nextToken():將StringTokenizer的下一個Token用String表示

以下是簡單的範例:



import java.util.StringTokenizer;



public class StringDemo {


 public static void main(String[] args) {

  String demo = "String,int,long,double";



  StringTokenizer st = new StringTokenizer(demo,",");

 

  System.out.println("st has "+st.countTokens()+"tokens");

 

  while(st.hasMoreTokens()){

   System.out.println();

  }

 }

}

2015年10月15日 星期四

[Java面試考題]Map處理

今天去松凌科技面試時遇到的考題
限時30分鐘
做出來後我問了一下面試官說能不能把考題公佈
面試官很慷慨的答應了,表示說他們也希望大家都能夠會處理map
於是我回家後馬上將這題題目重現
中文的註解可能有些誤差,以下是題目跟參考解答
題目詳細內容請見註解




import java.util.HashMap;
import java.util.Map;

public class RightLeft {

Map<String, Integer> left;
Map<String, Integer> right;

public void setUp(){
left = new HashMap<String, Integer>();
left.put("a", 1);
left.put("b", 2);
left.put("c", 3);

right = new HashMap<String, Integer>();
right.put("b", 2);
right.put("c", 4);
right.put("d", 5);

}

/*
* <pre>
* 備住:有兩個Map left right,請在Test()內完成程式碼輸出以下內容
*
* 1.key一樣value不一樣的內容
* 2.key一樣value一樣的內容
* 3.key只存在left不存在right的內容
* 4.key只存在right不存在left的內容
*
*/

public void Test(){

//answer of 1
System.out.println("1.");
for(Object key:left.keySet()){
if(right.get(key)!=null){
if(!right.get(key).equals(left.get(key))){
System.out.println("left key="+key+", value="+left.get(key));
System.out.println("right key="+key+", value="+right.get(key));
}
}
}

//answer of 2
System.out.println("2.");
for(Object key:left.keySet()){
if(right.get(key)!=null){
if(right.get(key).equals(left.get(key))){
System.out.println("left: key="+key+", value="+left.get(key));
System.out.println("right: key="+key+", value="+right.get(key));
}
}
}

//answer of 3
System.out.println("3.");
for(Object key:left.keySet()){
if(right.get(key)==null){
System.out.println("left: key="+key+", value="+left.get(key));
}
}

//answer of 4
System.out.println("4.");
for(Object key:right.keySet()){
if(left.get(key)==null){

System.out.println("right: key="+key+", value="+right.get(key));

}
}


}



public static void main(String[] args) {
RightLeft demo = new RightLeft();
demo.setUp();
demo.Test();

}

}

2015年10月11日 星期日

[Java]如何求N個整數的最大公因數

這個問題我認為原理非常的簡單...我在學Java的第一週就可以把他做出來
不過後來時間久了就忘記要把這個問題的解法丟上來

趁著現在比較有空的時間把教學簡單的打一下


首先從兩個整數的最大公因數開始
整數的最大公因數就是能夠同時整除他們的最大整數
求最大公因數的方法有很多種,其中一種方法叫做輾轉相除法
我們直接拿30跟18這兩個整數做例子
30/18=1餘12
18/12=1餘6
12/6=2

由於6整除了,所以30跟18的最大公因數就是6

從例子我們知道做法就是如果兩數沒有整除,就把原來的除數當做被除數,把餘數當做除數繼續除下去,直到兩數整除為止

於是我們可以知道求a,b兩數的最大公因數,相當於求b與a,b的餘數的最大公因數
以下就是簡單的範例,我們用一般的while迴圈展示輾轉相除法的演算法
另外使用遞迴當做參考

public class Gcd {



 public static void main(String[] args) {  

  //demo1

  System.out.println(gcd(18,12));

    

  //demo2

  System.out.println(gcd2(30,18));  



 }



 public static int gcd(int m, int n){

  int result = 1;

  while(m%n!=0){

   result=n;   

   n=m%n;

   m=result;

  }

  result=n;

  

  return result;

 }

 

 public static int gcd2(int m, int n){

  if(m%n==0){

   return n;

  } else {

   return gcd2(n,m%n);

  }  

 } 

}


接下來三個整數的最大公因數就是將前兩個最大公因數跟第三個數字做最大公因數
四個整數的最大公因數則是將三個整數的最大公因數與第四個數字做最大公因數...
以此類推
以下程式碼就只用while迴圈當範例,遞迴的寫法請自情參考兩個整數的程式碼


public class Gcd {



 public static void main(String[] args) {

  

  //demo1

  int[] x = new int[] {18,12,30};  

  System.out.println(dogcd(x));  

  

  //demo2 

  int[] y = new int[] {15,18,30,42,9};

  System.out.println(dogcd(y));

 }

 

 public static int dogcd(int[] input){

  for(int i=0;i<input.length-1;i++){

   input[i+1] = gcd(input[i],input[i+1]);

      

  }  

  return input[input.length-1];

 }



 public static int gcd(int m, int n){

  int result = 1;

  while(m%n!=0){

   result=n;   

   n=m%n;

   m=result;

  }

  result=n;

  

  return result;

 }
  

}

2015年10月7日 星期三

[雜談]由數學學習談程式語言學習

最近跟人聊天發現有人學程式的方法
發現其實跟人學數學的方法有異曲同工的感覺

數學其實跟程式是非常相似的東西,常常有人講說數學重理解
也有人覺得數學就是背公式多解題就學會了
當然不同職業需求的人需要學到的程度會有一些差別
但是我覺得學數學的人有幾個程度的差別
比如說求三角型面積好了

知道底乘以高除以二的公式的人至少比不知道公式的人學的好

了解到因為平行四邊型面積是底乘以高
兩個三角型的面積剛好等於平行四邊型面積的人又可以不用死背造成公式的誤用

但是學數學還有一種能力也很重要
你有沒有辦法在不知道三角型面積怎麼算的時候
發現說你只要能會算平行四邊型的面積就能夠求三角型的面積
最後發現由長方型的面積是長乘與寬,然後推得平型四邊型的面積是底乘以高

若是可以學得分解問題以及將未知問題與已知的知識連結的能力的話
學習程式就相對的簡單了
應該要把大功能拆成小步驟
比如說現在要按一個按紐後將三個網頁上輸入的數字做運算後顯示在畫面上
那麼你至少可以知道說
1.按紐需要一個onclick事件
2.onclick事件裡面的function需要抓三個變數
3.再來把三個變數做運算
4.最後將某個div的值改成運算的結果

這些事情每一步都不難,問題講成一個需求時為什麼做不出來?
就是因為沒有去把需求分解成好幾個做的出來的步驟,然後一步步把每個步驟完成

當然,你對程式語言越熟你就越能夠把程式做出來,因為你拆解步驟的同時你也會思考這個
解決方案到底程式做不做的出來,所以除了學習如何拆解問題以外
多學習程式語言裡面的函式庫怎麼用是一定有幫助的

2015年10月6日 星期二

[Java]費氏數列

費氏數列(fibonacci sequence)是程式語言中常見的遞迴範例
他的每一項分別是:
A0=0
A1=1
AN=A(N-1)+A(N-2)
也就是A2以後,每一項的值就是前兩項的值相加
使用遞迴的方法可以把費式數列的值做出來
以下是遞迴的範例


public class FibonacciTest {

  

 public static void main(String[] args) {
    
   System.out.println(fibonacci(50));    

 }

  

 public static long fibonacci(int x){

  if(x==1||x==2){

   return 1;

  }else {

   return fibonacci(x-1)+fibonacci(x-2);

  }  

 }  

}




但是使用遞迴的效能很差
所以如果有人提出這個問題
又沒有特別規定要用遞迴做出來的話
建議使用一般的迴圈來解決這個問題
效能會有明顯的改善
以下是範例


public class FibonacciDemo {



 public static void main(String[] args) {

  

  FibonacciDemo demo = new FibonacciDemo();

  System.out.println(demo.fibonacci(50));  

 }

 

 public long fibonacci(int n){

  if(n==0){

   return 0;

  } else {

   long x_1 = 0;

   long x_2 = 1;

   for(int i=0;i<n;i++){

    if(i>0){

     x_2 = x_2 + x_1;

     x_1 = x_2 - x_1;

    }
   
   }

   return x_2;

  }

 }


}