Text Justification

        Given an array of words and a length L, format the text such that each line has exactly L characters and is fully(left and right) justified.

        You should pack your words in a greedy approach; that is, pack as many words as you can in each line.  

        Pad extra spaces ' ' when necessary so that each line has exactly L characters.

        Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line do not divide evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right.        

        For the last line of text, it should be left justified and no extra space is inserted between words.

        For example,

words: ["This", "is","an", "example", "of", "text","justification."]

L: 16.

        Return the formatted lines as:

[

   "This   is    an",

   "example  of text",

   "justification.  "

]

        Note: Each word is guaranteed not to exceed L in length.

Corner Cases:

        A line other than the last line might contain only one word. What should you do in this case?

        In this case, that line should be left-justified.

 

        思路:题目要求进行文本格式化,每一行的宽度必须为L,且除了最后一行之外,单词要均匀分布,也就是单词间的空格数要尽量均匀,类似于word中的两端对齐。最后一行与其他行的格式化要求不同,它只需要左边对其就行。

        本题不需要什么高深的算法,但是更偏实际一些。解题思路就是从左向右扫描words,找到能放到一行中的所有单词,然后根据单词总数,所有单词中字符的总数,以及L得到空格总数,空槽位(the empty slots)数,以及每个空槽位包含的空格数。

        比如,如果单词数为a,则空槽位数为a-1,如果单词中所有字符总数为b,则空格总数就是L-b。要把L-b个空格均匀的分布到a-1个空槽位中。

        若无法做到完全均匀,需要将所有的空槽位分为左右两组,左边的槽位包含的空格数要比右边的多1。假设总空格数为m,槽位数为n,设左槽位数为x,则右槽位数y=n-x。右槽位中包含的空格数为t=m/n。所以,左槽位中包含的空格为t+1。可以得到下面的关系式:

x(t+1) + y(t) = m               --->

xt + x + nt – xt = m           --->

x = m – nt

        所以,左槽位数为m-nt,得到了左槽位数之后,就可以根据左、右槽位数,槽位中的空格数,均匀的分布单词了。

        代码如下,下面的代码中,使用了格式化输出中的%*语法:在转换说明中,宽度或精度可以用星号*表示,这时,宽度或精度的值通过转换下一参数(必须为int类型)来计算:

char * reformat(char **words, int startpos, int endpos, int charslen, int maxWidth)
{
	char *buf = calloc(maxWidth+1, sizeof(char));
	int wordcnts = endpos-startpos;

	int leftspacelen = 0;
	int rightspacelen = 0;
	int leftcnts = 0;
	int rightcnts = 0;

	int spacecnts = 0;
	int spaceslen = 0;
	
	int i;

	if(wordcnts == 1)
	{
		rightspacelen = maxWidth-charslen;
		sprintf(buf, "%s%*s", words[startpos], rightspacelen, "");
		return buf;
	}

	/*
	 spacecnts表示空槽位(empty slots)的个数,也就是单词数减1
	 spaceslen表示空格的总数
	 为了尽量均匀,将所有空槽位分成左右两部分
	 leftcnts表示左边槽位的个数
	 rightcnts表示右边槽位的个数
	 leftspacelen表示每个左边槽位包含的空格数
	 rightspacelen表示每个右边槽位包含的空格数
	*/

	spacecnts = wordcnts - 1;
	spaceslen = maxWidth-charslen;
	leftcnts = spaceslen - spacecnts * (spaceslen/spacecnts);
	rightcnts = spacecnts - leftcnts;
	leftspacelen = spaceslen/spacecnts + 1;
	rightspacelen = spaceslen/spacecnts;
	

	sprintf(buf, "%s", words[startpos]);


	for(i = startpos+1; i < endpos; i++)
	{
		if(i - startpos <= leftcnts)
		{
			sprintf(buf+strlen(buf), "%*s%s", leftspacelen, "", words[i]);
		}
		else
		{
			sprintf(buf+strlen(buf), "%*s%s", rightspacelen, "", words[i]);
		}
	}
	return buf;
}



char** fullJustify(char** words, int wordsSize, int maxWidth, int* returnSize) 
{
	int i;
	char *buf = NULL;

	int leftlen = 0;
	int wordlen = 0;
	int charslen = 0;

	int startpos = 0;
	int endpos = 0;

	char **res = calloc(wordsSize, sizeof(char *));
	int reslen = 0;

        /*
		扫描words数组,看哪些单词可以放到一行中
		startpos表示起点索引,endpos-1表示终点索引
		所以,endpos-startpos就表示一行中单词的总数
		charslen表示一行中字母的总数
	*/

	leftlen = maxWidth;
	for(i = 0; i < wordsSize; i++)
	{
		if((wordlen = strlen(words[i])) > leftlen)
		{
			res[reslen++] = reformat(words, startpos, endpos, charslen, maxWidth);
			startpos = endpos;
			leftlen = maxWidth;
			charslen = 0;
		}
		
		charslen += wordlen;
		endpos++;
		leftlen -= wordlen+1;
	}	

	/*
		最后一行特殊处理,根据题目要求,
		最后一行的单词间只能有一个空格
	*/
	buf = calloc(maxWidth+1, sizeof(char));
	for(i = startpos; i < endpos; i++)
	{
		if(i < endpos-1)
			sprintf(buf+strlen(buf), "%s ", words[i]);
		else
			sprintf(buf+strlen(buf), "%s", words[i]);
	}

	//填充最后一行剩下的空格
	sprintf(buf+strlen(buf), "%*s", maxWidth-strlen(buf), "");
	res[reslen++] = buf;

	*returnSize = reslen;
	return res;
}


posted @ 2015-09-10 22:15  gqtc  阅读(132)  评论(0编辑  收藏  举报