1. 程式人生 > >演算法題(十八):搜狗19年校招程式設計題(一)——找區間

演算法題(十八):搜狗19年校招程式設計題(一)——找區間

注:筆試時並沒有AC,線下修改後可以輸出示例結果。

問題:從一個序列中找出所有包含全部數字的最小索引區間,若有多個則按出現的順序輸出。

輸入輸出示例:

輸入:1 1 3 4 6 6 5 1 1 3 3

輸出:[2,7] [3,8] [4,9]

分析:先用一個list1來記錄陣列所有不重複的數字,再以0作為區間開始點,遍歷陣列(雙重for迴圈),用一個list2來記錄遍歷過程中所有不重複的數字,遍歷過程中判斷list2的大小是否與list1相同,若相同則停止該輪遍歷,並將停留點作為區間結束點。一趟結束後,再以該區間的開始點的下一個點作為新開始點進行遍歷,重複直到新起點超過陣列界限。需要注意的是在剛開始遍歷時,可能出現類似“1,1,1”這樣連續相同數字,為了求最小區間,應該把區間的開始點設為最後一個“1”的索引。

程式碼:

import java.util.ArrayList;
import java.util.Stack;
public class Main{
    
    public static void main(String[] args){

            int N = 10;
            int[] num ={1,1,2,2,3,2,1,3,2,1};
            //記錄num中不重複的數
            ArrayList<Integer> list = new ArrayList<Integer>();
            for(int i=0; i<N; i++){
                if(!list.contains(num[i])){
                    list.add(num[i]);
                }
            }
            //記錄遍歷過程中不重複的數
            ArrayList<Integer> list2 = new ArrayList<Integer>();
            //記錄每趟遍歷的起點,用於應付“1,1,1”這樣的情況
            Stack<Integer> stack = new Stack<Integer>();
            //記錄每趟的起點
            Stack<Integer> startStack = new Stack<Integer>();
            //記錄每趟的終點
            Stack<Integer> endStack = new Stack<Integer>();
            //為了按順序輸出,而準備,棧的逆序
            Stack<Integer> startStack2 = new Stack<Integer>();
            //為了按順序輸出,而準備,棧的逆序
            Stack<Integer> endStack2 = new Stack<Integer>();
            int start = -1;
            int end = -1;
            //第一趟從0開始,之後從start+1開始遍歷
            for(int i=0; i<N; i++){
            	start = start+1;
            	end = -1;
            	//判斷是否剛開始遍歷,用於應付“1,1,1”這樣的情況
                boolean begin1 = true;
               //用於判斷是否連續,用於應付“1,1,1”這樣的情況
                int idx = start;
                //如果開始遍歷到結束的長度小於list,則說明之後的遍歷無意義,故停止遍歷
                if(N-start<list.size()){
                    break;
                }
                for(int j=start; j<N; j++){
                	//list2也只記錄不重複的數字
                   if(!list2.contains(num[j])){
                       if(begin1){
                           stack.push(num[j]);
                           begin1 = false;
                           
                       }
                       list2.add(num[j]);
                   }else{
                	   //判斷剛開始遍歷時的連續情況“1,1,1”
                       if(stack.peek() == num[j] && j == idx+1){
                           start = j;
                           idx++;
                       }
                   }
                   //若已經全部找到數字,則結束該趟遍歷
                   if(list.size() == list2.size()){
                        end = j;
                        list2.clear();//需要清空list2,以為下次所用
                        break;
                   }
                }
                //如果end不是初始值,說明遍歷有意義
                if(end != -1){
                    startStack.push(start+1);
                    endStack.push(end+1);
                }
            }
            int size = startStack.size();
            //反轉棧
            while(!startStack.isEmpty()){
                startStack2.push(startStack.pop());
                endStack2.push(endStack.pop());
            }
            //最終輸出結果
            String res = "";
            int index = 0;
            while(!startStack2.isEmpty()){
                res += "["+startStack2.pop()+","+endStack2.pop()+"]";
                index++;
                //最後一個區間後面不加空格
                if(index == size){
                    
                }else{
                    res +=" ";
                }
                
            }
            System.out.println(res);
    }
}

輸出:[2,5] [4,7] [5,7] [6,8] [7,9] [8,10]