01/10/2018, 09:43

Nhờ mọi người cho mình hướng đi của bài tập sau!

Xin chào mn, mình đc thầy giao 1 bài tập như sau:

Cho 1 số nguyên dương được nhập từ bàn phím, hãy sắp xếp các chữ số của số đó theo thứ tự tăng dần tạo thành 1 số mới. In số mới ra màn hình. (Chỉ sử dụng kiến thức câu điều kiện & rẽ nhánh, vòng lặp, hàm, không đc sử dụng mảng)
Bài này thầy nói làm bằng C.

Mn có thể cho mình xin hướng làm đc ko ạ (tối ưu hoặc ko tối ưu). Sau đó mình tự code cũng đc vì mình biết nếu xin code là vi phạm nội quy
Mình xin cảm ơn trc !

Tao Không Ngu. viết 11:51 ngày 01/10/2018

Hi Nguyễn Thanh Việt
Có vấn đề gì nhỉ ? Bóc mảng chứ số ra. Xắp xếp. In ra.

Nguyễn Thanh Việt viết 11:51 ngày 01/10/2018

Mình chưa hiểu lắm, bạn có thể nói hơn đc ko? (mình chưa học mảng nên ko thể áp dụng đc, vả lại thầy cũng yêu cầu làm bằng hàm, thủ tục thôi ạ!)

2D_team_free_online_Education viết 11:50 ngày 01/10/2018

không được sử dụng mảng thì bạn có thể tách các số riêng ra hàng chục , hàng trăm, đơn vị, nghìn…, rồi lưu lại vào biến , sau đó sắp xếp , rồi gán lại ,

Đào An viết 11:55 ngày 01/10/2018
  1. Tách các chữ số của số . (chia cho 10 lấy phần dư)
    vd 4352 chia 10 dư (2) thương là 435 chia tiếp cho 10 dư (5) --> ra các chữ số nhá
    nhét các chữ số này vào mảng.
  2. Rồi so sánh xếp mảng theo thứ tự tăng dần
  3. In ra
Nguyễn Thanh Việt viết 11:46 ngày 01/10/2018

không được sử dụng mảng thì bạn có thể tách các số riêng ra hàng chục , hàng trăm, đơn vị, nghìn…, rồi lưu lại vào biến , sau đó sắp xếp , rồi gán lại ,

Trường hợp số có quá nhiều chữ số thì mình nghĩ dùng biến ko khả thi đâu bạn

@Dao_An Ko đc dùng mảng bạn ơi !!!

Trần Hoàn viết 11:53 ngày 01/10/2018

nếu đã không được dùng mảng, không biết bạn có được dùng danh sách liên kết không :))

2D_team_free_online_Education viết 11:47 ngày 01/10/2018

vì không sử dụng được mảng nên chỉ mình nghĩ sử dụng biến , nhưng không phải tất cả các biến , mà tách tới đâu so sánh tới đó , và lần tới chỉ cần so sánh với các giá trị từ nhỏ đến lớn , hạn chế được số biến

Tao Không Ngu. viết 11:50 ngày 01/10/2018

Hi Nguyễn Thanh Việt.
Bạn có thể coi số đó là 1 mảng luôn rồi chiển khai xắp xếp trên đó.

hunter viết 11:49 ngày 01/10/2018

Dùng số dương đấy chia cho 10 tới số cuối cùng sau đấy thực hiện so sánh rồi sắp xếp…!
Mình nghĩ thuật toán là thế.

Nguyễn Thanh Việt viết 11:52 ngày 01/10/2018

không biết bạn có được dùng danh sách liên kết không :))

Hình như Linked List có liên quan tới struct và pointer dug ko a? E chưa học nên chắc ko đc

vì không sử dụng được mảng nên chỉ mình nghĩ sử dụng biến , nhưng không phải tất cả các biến , mà tách tới đâu so sánh tới đó , và lần tới chỉ cần so sánh với các giá trị từ nhỏ đến lớn , hạn chế được số biến

Bạn nói rõ hơn đc ko? Mình cũng hiểu sơ sơ ý bạn những chưa hình dung đc lắm

Bạn có thể coi số đó là 1 mảng luôn rồi chiển khai xắp xếp trên đó.

Bằng cách nào a?

Dùng số dương đấy chia cho 10 tới số cuối cùng sau đấy thực hiện so sánh rồi sắp xếp…!

Vậy mỗi chữ số khi % cho 10 lưu ở đâu?

Tao Không Ngu. viết 11:53 ngày 01/10/2018

Hi Nguyễn Thanh Việt.
Bạn muốn đổi chỗ hai chữ số a vị trí indexOfA và b indexOfB của só n

n += (a - b)*(10^indexOfB - 10^indexOfA);

Công việc là tìm a, b, indexOfA, indexOfB.
Bạn đã có hàm swap hai số bây giờ công việc còn lại của bạn là áp dụng thuật toán xắp xếp trên đó.

2D_team_free_online_Education viết 11:49 ngày 01/10/2018

thì bạn so sánh cái bạn xóa luôn biến đó đi , thì sẽ hạn chế tối đa , với cả trăm biến là bình thường , nên vấn đề về số lượng biến không phải là lớn:3

Hung viết 11:48 ngày 01/10/2018

Ban đầu bạn cứ làm mảng đi, rồi sau đó chỉnh code lại là thành bài tập không sử dụng mảng.
Mình giả sử biến lưu trữ nhận từ input là input và có kiểu Int

result = array[index] thì có hàm result = getNumber(input, index) trả về chữ số ở vị trí index.
array[index] = value thì thành setNumber(input, value, index) thay chữ số vị trí thứ index của input thành value.

Hiện thực thêm 3 hàm count, prependappend đếm số phần tử trong mảng, chèn 1 số vào trước hoặc sau mảng, ví dụ:
input = 243112
cout << cout(input) // giá trị là 6

input = 12
prepend(input, 2)
cout << input; // có giá trị 212

input = 21
append(input, 4)
cout << input // có giá trị 214

Rồi trong bài giải mảng ban đầu bạn thay thế các câu lệnh mảng thành các hàm bạn đã tạo. Hoàn thành bài tập mà không dùng mảng.

Mato Nguyen viết 11:48 ngày 01/10/2018

Chắc không cần mảng bạn ah, mình viết thử như sau:

#include<stdio.h>
#include<conio.h>
#include<math.h>

int main(){
	long x, y, a, b;
	int count = 0;
	int i, j;
	
	printf("Nhap vao so nguyen duong: ");
	scanf("%ld",&x);
	
	//Xác định số chữ số
	
	//Thực hiện giải thuật sắp xếp: duyệt các chữ số trong số ban đầu, đổi chỗ nếu không đúng vị trí
	
	printf("So moi: %ld\n",x);
	return(0);
}
HK boy viết 11:50 ngày 01/10/2018

Hoàn toàn không cần mảng, nhưng rất tốn biến :v
Rõ ràng là ta thấy các chữ số chỉ từ 0…9. Lập 10 biến cnt0, cnt1,..., cnt9 là số lần xuất hiện của các chữ số 0, 1,..., 9.
Duyệt các chữ số trong số n:

while (n > 0) {
    int d = n % 10; //lấy chữ số cuối cùng
    if (d == 0) cnt0++; else
    if (d == 1) cnt1++; else
    ... //đoạn này bạn tự viết tiếp, mà có thể viết được bằng switch case, nhưng mình quên mất rồi
    if (d == 9) cnt9++;
    n /= 10; //bỏ chữ số cuối cùng
}

Cuối cùng thì:

for (int i=0; i<cnt0; i++) printf('0');
for (int i=0; i<cnt1; i++) printf('1');
...
for (int i=0; i<cnt9; i++) printf('9');

À mà bạn tự cải tiến vụ có chữ số 0 ở đầu nhé.

Tao Không Ngu. viết 11:51 ngày 01/10/2018

HI Mato Nguyen
Không up code.

Nguyễn Thanh Việt viết 11:44 ngày 01/10/2018

Cuối cùng thì:

Mình làm theo cách bạn này cũng khá ok nè, nhưng khúc cuối mình lưu nó vào 1 biến kết quả và return về chứ ko in ra

// gcc *.c -o main -lm -Wall && ./main
#include <stdio.h>
#include <math.h>

int NewNumber(int n)
{
	int scs0, scs1, scs2, scs3, scs4, scs5, scs6, scs7, scs8, scs9;
	scs0 = scs1 = scs2 = scs3 = scs4 = scs5 = scs6 = scs7 = scs8 = scs9 = 0;
	int n_digit = log10((double)n), newNumber; 
	while (n > 0) {
		switch(n % 10) {
			case 0: ++scs0; break;
			case 1: ++scs1; break;
			case 2: ++scs2; break;
			case 3: ++scs3; break;
			case 4: ++scs4; break;
			case 5: ++scs5; break;
			case 6: ++scs6; break;
			case 7: ++scs7; break;
			case 8: ++scs8; break;
			case 9: ++scs9; break;
			default: break;
		}
		n /= 10;
	}
	for (int i = 0; i < scs9; ++i) newNumber += 9 * ceil(pow(10.0, (double)n_digit--));
	for (int i = 0; i < scs8; ++i) newNumber += 8 * ceil(pow(10.0, (double)n_digit--));
	for (int i = 0; i < scs7; ++i) newNumber += 7 * ceil(pow(10.0, (double)n_digit--));
	for (int i = 0; i < scs6; ++i) newNumber += 6 * ceil(pow(10.0, (double)n_digit--));
	for (int i = 0; i < scs5; ++i) newNumber += 5 * ceil(pow(10.0, (double)n_digit--));
	for (int i = 0; i < scs4; ++i) newNumber += 4 * ceil(pow(10.0, (double)n_digit--));
	for (int i = 0; i < scs3; ++i) newNumber += 3 * ceil(pow(10.0, (double)n_digit--));
	for (int i = 0; i < scs2; ++i) newNumber += 2 * ceil(pow(10.0, (double)n_digit--));
	for (int i = 0; i < scs1; ++i) newNumber += ceil(pow(10.0, (double)n_digit--));
	for (int i = 0; i < scs0; ++i) {
		newNumber *= 10;
		--n_digit;
	}
	return newNumber;
}

int main()
{
	int n;
	printf("Type n = ");
	scanf("%d", &n);
	printf("Result: %d\n", NewNumber(n));
	return 0;
}

Ban đầu bạn cứ làm mảng đi, rồi sau đó chỉnh code lại là thành bài tập không sử dụng mảng.

Mình chưa học tới bài mảng sao dùng đc @@ Vả lại còn chưa học C++

với cả trăm biến là bình thường , nên vấn đề về số lượng biến không phải là lớn:3

Mình ko ngại khi số lượng biến cần dùng là nhiều, mình chỉ ngại vì bài này mà dùng biến thì các biến sẽ khai báo với số lượng “bị động”, tức là ko biết trc bao nhiêu để khai báo, nên mình nghỉ ko khả thi

@Phong_Ky_Vo Để e suy nghĩ theo cách anh thử, nhưng việc tìm indexofA và indexofB hơi khó đấy !

HK boy viết 11:53 ngày 01/10/2018

Cái đoạn cộng số ấy, sao bạn không dùng n = n * 10 + i để chắc chắn không bị sai số? Động đến float là cực kì nguy hiểm. Tốt nhất là không dùng trong trường hợp không cần thiết.
Bài này cũng không cần thiết phải dùng đến ceil, pow, floor,… các kiểu. Cứ dùng

for (int i=0; i<cnt0; i++) n = n * 10 + 0;
for (int i=0; i<cnt1; i++) n = n * 10 + 1;
...
for (int i=0; i<cnt9; i++) n = n * 10 + 9;

là chắc chắn đúng, có sai là do mình code thôi :v

Đẵng Nguyễn Quốc viết 11:54 ngày 01/10/2018

Vấn đề cuối cùng của bạn là ra một số mà các chữ số trong con số đó được sắp xếp tăng dần. ( 5231 ) -> ( 1235 )

Nếu như vầy, thì bạn dùng phép tách số bằng việc chia cho 10 lấy dư.

  • Một biến lưu số dư sau phép chia.
  • Một biến lưu số sau khi tách từng số.
  • Một biến lưu số cuối cùng.
    Nói cho dễ hiểu là vầy
    N = 5231
    Chia lấy dư lần 1 => số dư là 1 , số sau khi tách số là 523
    Số cuối cùng lần 1 = 1
    Chia lấy dư lần 2 => số dư là 3 , số sau khi tách số là 52
    Số cuối cùng lần 1 = 1*10 + 3 = 13
    Tương tự cho lần sau.
HK boy viết 11:48 ngày 01/10/2018

Trông hơi hư cấu nhỉ :v nhưng sao chia lấy dư lần 2 là 3, mà số cuối cùng là 12?

Bài liên quan
0