My clean Java solution, very easy to understand


  • 219
    H
    private final String[] LESS_THAN_20 = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
    private final String[] TENS = {"", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
    private final String[] THOUSANDS = {"", "Thousand", "Million", "Billion"};
    
    public String numberToWords(int num) {
        if (num == 0) return "Zero";
    
        int i = 0;
        String words = "";
        
        while (num > 0) {
            if (num % 1000 != 0)
        	    words = helper(num % 1000) +THOUSANDS[i] + " " + words;
        	num /= 1000;
        	i++;
        }
        
        return words.trim();
    }
    
    private String helper(int num) {
        if (num == 0)
            return "";
        else if (num < 20)
            return LESS_THAN_20[num] + " ";
        else if (num < 100)
            return TENS[num / 10] + " " + helper(num % 10);
        else
            return LESS_THAN_20[num / 100] + " Hundred " + helper(num % 100);
    }

  • 0
    W

    you can combine ones and lesThan20 into one array and get rid of one branch in your helper function


  • 0
    H

    Good suggestion!!! I've changed it. Thank you very much!!!


  • 0
    M

    Run Time 72 ms


  • 0
    S
    This post is deleted!

  • 0
    H

    Since this problem asks us to convert a "non-negative" integer into its English words representation, we don't need to consider negative cases.


  • 19
    U
    public class Solution {
    public String numberToWords(int num) {
        if (num == 0) return "Zero";
        String[] lessThan20Words = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
        String[] tyWords = {"Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
        String[] dexWords = {"Billion", "Million", "Thousand", "Hundred"};
        int[] radix = {1000000000,1000000, 1000, 100};
        StringBuffer sb = new StringBuffer();
        int count = 0;
        for (int i = 0; i < radix.length; ++i) {
            count = num / radix[i];
            if (count == 0) continue;
            sb.append(numberToWords(count) + " ");
            sb.append(dexWords[i] + " ");
            num %= radix[i];
        }
        if (num < 20) {
            sb.append(lessThan20Words[num]);
        }else {
            sb.append(tyWords[num / 10 - 2] + " ");
            sb.append(lessThan20Words[num % 10]);
        }
        return sb.toString().trim();
    }
    

    }


  • 1
    V

    I believe this would return "" for num = 1000?


  • 8
    A

    I tried to combine the two solutions here and came up with my version, just to provide some additional thought. Thank you for the previous two great methods.

    final String[] LESS_THAN_20 = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
    final String[] TENS = {"", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
    final String[] THOUSANDS = {"Billion", "Million", "Thousand", ""};
    final int[] radix = {1000000000, 1000000, 1000, 1};
    
    public String numberToWords(int num) {
        if (num == 0) return "Zero";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < radix.length; i++) {
            if (num / radix[i] == 0) continue;
            sb.append(trans(num / radix[i])).append(THOUSANDS[i]).append(' ');
            num %= radix[i];
        }
        return sb.toString().trim();
    }
    
    private String trans(int num) {
        if (num == 0) return "";
        if (num < 20) return LESS_THAN_20[num] + " ";
        if (num < 100) return TENS[num / 10] + " " + trans(num % 10);
        return LESS_THAN_20[num / 100] + " Hundred " + trans(num % 100);
    }

  • 0
    Y

    Can anyone explain how to realize trim() in C++?


  • 1

    @hwy_2015 Hi, Thank your clean solution. I wrote a C++ recursive version based on your clear code.
    @Yan_Sylvia_Liu Hi, you can use find_first_not_of(' ') and find_last_not_of(' ') in C++ to implement trim() in java

    private:
        string LESS20[20] = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve",                                "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
        string TENS[10] = {"", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
        string THOUSANDS[4] = {"", "Thousand", "Million", "Billion"};
    public:
        string Less1000(int num)
        {
            if(num==0) return "";
            if(num<20) return  LESS20[num] + " ";
            if(num<100) return TENS[num/10] + " " + Less1000(num%10);
            return LESS20[num/100] + " Hundred "  + Less1000(num%100);
        }
        string numberToString(int num, int i)
        {
            if(num==0) return "";
            if(num%1000==0) return numberToString(num/1000, i+1);
            return numberToString(num/1000, i+1) + Less1000(num%1000)  + THOUSANDS[i] + " ";
        }
        string numberToWords(int num) {
            if(num==0) return "Zero";
            string res = numberToString(num, 0);
            return res.substr(0, res.find_last_not_of(' ')+1);
        }
    

  • 0

    Nice solution. Using StringBuilder instead of String can be faster and consuming less memory.


  • 0
    K

    @uucoder awesome solution....I love it. Way better and faster than original one posted earlier....


  • 0
    R

    This solution is brilliant!


  • 0
    T

    whats the complexity of this func ?


  • 0
    F
    private final String[] map1 = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
    private final String[] map2 = {"", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
    private final String[] map3 = {"", " Thousand", " Million", " Billion"};
    
    
    
    
    public String numberToWords(int num) {
        if (num == 0) return "Zero";
        
        int weight = 0;
        StringBuilder sb = new StringBuilder();
                
        while (num > 0) {
            int n = num % 1000;
            String s = getEng(n);
            
            if(s.length() != 0) {
                sb.insert(0, " " + s + map3[weight]);   
            }               
            weight++;           
            num = num / 1000;
        }
        
        return sb.toString().trim();
    }
    
    public String getEng (int num) {
        if (num == 0)
            return "";
        
        StringBuilder sb = new StringBuilder();
        
        int h = num / 100;
        if(h != 0) {
            sb.append(map1[h] + " " + "Hundred");
        }
        
        num = num % 100;
        if(num < 20) {
            sb.append(" " + map1[num]);
            return sb.toString().trim();
        }
        
    
        int t = num / 10;
        if(t != 0) {
            sb.append(" " + map2[t]);
        }
        num = num % 10;
        if(num != 0) {
            sb.append(" " + map1[num]);
        }
        
        return sb.toString().trim();
    }
    
    non recurrsion version

  • 0
    S

    I think the time complexity is O(1) in each recursive call. Is my thought correct?


Log in to reply
 

Looks like your connection to LeetCode Discuss was lost, please wait while we try to reconnect.