今年春招拼多多面試時的算法題。
面試官的意思是,任意給你一個數n,然後對應一個n*n的矩陣,然後順時針從1開始填入矩陣中,一直到填滿。
如n=3,
1 2 3
8 9 4
7 6 5
package cn.dlpu.lby;
import java.util.Scanner;
public class Xuanzhuantianru {
/*順時針螺旋填入
從鍵盤輸入一個整數(1~20)
則以該數字爲矩陣的大小,把1,2,3…n*n 的數字按照順時針螺旋的形式填入其中。例如:
輸入數字2,則程序輸出:
1 2
4 3
輸入數字3,則程序輸出:
1 2 3
8 9 4
7 6 5
輸入數字4, 則程序輸出:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int [][] m = new int[n][n];
rotating(n,m);
print(n,m);
}
private static void print(int n, int[][] m) {
// TODO Auto-generated method stub
for(int i = 0;i<n;i++){
for(int j=0;j<n;j++){
System.out.printf("%4d",m[i][j]);
}
System.out.print("\n");
}
}
private static void rotating(int n, int[][] m) {
// TODO Auto-generated method stub
int k = 1;
for(int i=0;i<=n/2;i++){
for(int j = i;j<n-i;j++){
m[i][j] = k++; //上方行方向
}
for(int j = i+1;j<n-i;j++){
m[j][n-i-1] = k++; //右側列方向
}
for(int j = n-i-2;j>=i;j--){
m[n-i-1][j] = k++; //下方行方向
}
for(int j = n-i-2;j>i;j--){
m[j][i] = k++; //左側列方向
}
}
}
}
還有一題:
問題描述:
現有一直線,從原點到無窮大。
這條直線上有N個線段。線段可能相交。
問,N個線段總共覆蓋了多長?(重複覆蓋的地區只計算一次)
================================================
解題思路:
可以將每個線段拆分成“單位1”
遍歷所有線段,使用一個數組記錄每個線段所走過的“單位1”
最後統計數組中被走過的中“單位1”的個數,即是所有線段覆蓋的總長度了。
這裏有個問題?數組的大小如何確定?
數組的大小應該是所有線段中最大的端點座標。
===============================================
順便想到一個問題。
給出若干個線段。求一共有幾個“連通域”。就是將能合併的線段 合併成一個線段。
最後能合併出幾個來?
利用上面的思想。非常簡單。
只需遍歷單位數組的時候做個開始和結尾的記錄就行了。
程序實現如下。
===============================================
- //此題要求
- //求出一條直線上所有線段所覆蓋的全程長度是多少。
- //重疊的地方只計算一次。
- //================================
- //本算法的思想是,將每個線段進行像素化,
- //添加到一個單位數組c[N]中
- //遍歷c數組判斷哪些單位被覆蓋到了,
- //在count計數一下就知道一共覆蓋了多少路程。
- //真是巧妙啊。
- //==============================
- #include <iostream>
- using namespace std;
- const int N = 10000;
- //線段結構體
- struct Segment
- {
- int start;
- int end;
- };
- //
- int coverage(Segment *segments, int n)
- {
- bool c[N]={false};//每個“單位1”是否被覆蓋到
- int start=0;
- int end = 0;
- //遍歷n個線段
- for(int i = 0; i < n; i++)
- {
- for(int j = segments[i].start; j < segments[i].end; j++)
- {
- c[j] = true;
- }
- //尋找最右端
- if(segments[i].end > end)
- {
- end = segments[i].end;
- }
- //尋找最左端
- if(segments[i].start < start)
- {
- start = segments[i].start;
- }
- }
- //從最左端開始到最右端。遍歷單位數組C
- int count = 0;
- for(int i= start; i < end; i++)
- {
- if(c[i])
- {
- int s=i;
- while(c[i])
- {
- count++;
- i++;
- }
- int e=i;
- cout << "["<<s<<","<<e<<"]"<<endl;
- }
- }
- return count;
- };
- int main()
- {
- Segment s1;
- s1.start = 1;
- s1.end = 3;
- Segment s2;
- s2.start = 2;
- s2.end = 6;
- Segment s3;
- s3.start = 11;
- s3.end = 12;
- Segment s4;
- s4.start = 10;
- s4.end = 13;
- Segment ss[] = {s1,s2,s3,s4};
- cout << "歸併後"<<endl;
- cout <<"被覆蓋總長度:" <<coverage(ss, sizeof(ss)/sizeof(ss[0]))<<endl;
- }
輸出結果如下:
歸併後
[1,6]
[10,13]
被覆蓋總長度
8
請按任意鍵繼續. . .