LeetCode算法題-Happy Number(Java實現)


這是悅樂書的第188次更新,第190篇原創

01 看題和准備

今天介紹的是LeetCode算法題中Easy級別的第47題(順位題號是202)。編寫算法以確定數字是否“幸福”。

幸福數字是由以下過程定義的數字:從任何正整數開始,將數字替換為其數字的平方和,並重復該過程,直到最后數字等於1。這個過程以1結尾的那些數字是幸福的數字。如果陷入無限循環則不是幸福數字。例如:

輸入:19
輸出:true
說明:
1x1 + 9x9 = 82
8x8 + 2x2 = 68
6x6 + 8x8 = 100
1x1 + 0x0 + 0x0 = 1

本次解題使用的開發工具是eclipse,jdk使用的版本是1.8,環境是win7 64位系統,使用Java語言編寫和測試。

02 第一種解法

從題目給的例子可以看出,每獲得一個新的數字,都需要按照個十百位拆分然后計算乘積,直到最后得到的是1為止,而那些不是幸福數字的數,會陷入死循環里面,因此,我們需要將每次新計算得到的結果保存起來,如果下次計算的時候遇到,可以直接判斷該數字不是幸福數字,因此我們使用HashMap來存值,使用遞歸來循環處理數據。因為需要多次使用Map,所以將其定義在方法外面,可以全局使用。

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
public boolean isHappy(int n) {
    if (n <= 0) {
    	return false;
    }
    if (n == 1) {
    	return true;
    }
    int index = 1;
    int sum = 0;
	for (int i=0; i <(n+"").length(); i++) {
    	sum += Math.pow((n+"").charAt(i)-'0', 2);
    }
	if (sum == 1) {
		return true;
	}
	if (map.containsKey(sum)) {
		return false;
	} else {
		map.put(sum, index++);
	}
    return isHappy(sum);
}

03 第二種解法

思路與上面一樣,不過使用的是迭代的方法,所以,定義的HashMap放在你方法里面。使用了兩層循環,外層控制map判斷key是否存在以及替換新的n,內層循環處理新數不同位整數的平方和。

public boolean isHappy2(int n) {
    if (n <= 0) {
    	return false;
    }
    if (n == 1) {
    	return true;
    }
    Map<Integer, Integer> map2 = new HashMap<Integer, Integer>();
    int index = 1;
    int sum = 0;
	while (true) {
		for (int i=0; i <(n+"").length(); i++) {
        	sum += Math.pow((n+"").charAt(i)-'0', 2);
        }
    	if (sum == 1) {
    		return true;
    	}
    	if (map2.containsKey(sum)) {
    		return false;
    	} else {
    		map2.put(sum, index++);
    	}
    	n = sum;
    	sum = 0;
	}
}

04 第三種解法

如果你算過幾個特殊的數,比如2、4、14、16、18,這些數字都會陷入死循環,並且是數字4.至於其他的數,如果不是幸福數,都會陷入死循環里面,死循環的入口就是4或者16,對此,我們可以不使用HashMap,只要判斷新得到的數是否等於4或者16即可表示此數字不是幸福數字。

此解法同樣是使用迭代的方法,借助兩層循環,外層做判斷,內層做不同位數字的平方和。

public boolean isHappy3(int n) {
	int sum = 0;
	while (sum != 1) {
		if (n == 4 || n == 16)
			break;
		while (n > 0) {
			int rem = n % 10;
			sum += rem * rem;
			n /= 10;
		}
		if (sum == 1)
			return true;
		n = sum;
		sum = 0;
	}
	return false;
}

05 第四種解法

使用HashSet,借助其不能存在重復元素的特性,思路和第一、第二種解法一樣,都是先去獲取新數的平方和,然后添加進HashSet,如果添加失敗,說明已經存在該整數,即不是幸福數。不過這里是改變了n的原始值,所以最后判斷的是n是否等於1。

public boolean isHappy4(int n) {
    HashSet<Integer> seen = new HashSet<>();
    while (seen.add(n)) {
        int square = 0;
        int sum = 0;
        while (n!=0) {
            square = n%10;
            sum += (square*square);
            n /=10;
        }
        n = sum;
    }
    return n==1 ? true : false;
}

06 第五種解法

借助環的思路。如果你還對之前的判斷一個鏈表是否存在環的那道題目有印象的話,那么此題是與之類似的,每次新得到的數就代表一個節點,如果此節點出現過一次,即表示此鏈表是有環的,也就是說明此數是幸福數。

借助雙指針,一個每次進行一次計算,另外一個每次計算兩次,相當於速度是前一個的兩倍,如果存在相同的數,兩個指針肯定會相遇。

public boolean isHappy5(int n) {
    int slow = n;
    int fast = n;
    do {
        slow = digitSquareSum(slow);
        fast = digitSquareSum(fast);
        fast = digitSquareSum(fast);
        if (slow == 1 || fast == 1) {
        	return true;
        }
    } while(slow != fast);
    return false;
}

public int digitSquareSum(int n) {
    int sum = 0, tmp;
    while (n > 0) {
        tmp = n % 10;
        sum += tmp * tmp;
        n /= 10;
    }
    return sum;
}

07 小結

算法專題目前已連續日更超過一個月,算法題文章47+篇,公眾號對話框回復【數據結構與算法】、【算法】、【數據結構】中的任一關鍵詞,獲取系列文章合集。

以上就是全部內容,如果大家有什么好的解法思路、建議或者其他問題,可以下方留言交流,點贊、留言、轉發就是對我最大的回報和支持!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM